home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Tools (InfoMagic)
/
Internet Tools.iso
/
dos_win
/
winsock
/
wsock20
/
ws2spi.txt
< prev
next >
Wrap
Text File
|
1994-12-16
|
397KB
|
9,224 lines
ii
Windows Sockets 2
Service Provider
Interface
A Service Provider Interface for Transparent Network
Programming under Microsoft Windows
Revision 20.043
December 79, 1994
Winsock 2
Subject to Change Without Notice
Disclaimer
Microsoft, Intel, and JSB disclaim all warranties and
liability for the use of this document and the information
contained herein, and assume no responsibility for any
errors which may appear in this document. Microsoft, Intel,
and JSB make no warranty or license regarding the
relationship of this document and the information contained
herein to the intellectual property rights of any party.
Microsoft, Intel, and JSB make no commitment to update the
information contained herein.
Winsock 2.0 Service Provider Interface
TABLE OF CONTENTS
TABLE OF CONTENTS iii
1. INTRODUCTION 1
1.1 Winsock Specification is a WOSA Component 1
1.1.1 Winsock 2 DLLs 1
1.2 Microsoft Windows and Windows-specific
extensions 2
1.3 Naming Conventions 2
2. OVERVIEW 3
2.1 Configuration of Winsock Service Providers 3
2.1.1 Registry Layout for Windows NT and
Windows 95 3
2.1.1.1 Providers 3
2.1.1.2 Provider-specific Keys 3
2.1.2 WINSOCK2.INI Layout for Windows 3.1 5
2.1.2.1 Providers 6
2.1.2.2 Provider-specific Sections
([Provider-<Provider Key>]) 6
2.2. Service Providers Interface Model 8
2.3 Initialization of Winsock Service Providers 8
2.4 Functionality Implemented Within the Winsock
DLL 9
2.5 Functionality Implemented by Service Providers 9
2.6 Differences and Similarities Between Winsock
API and SPI 9
2.7 Differences Between 32-bit and 16-bit Winsock
SPI 10
2.8 Sockets 10
2.8.1 Out-of-band data 10
2.8.2 Socket Options 11
2.9 Quality of Service (QOS) 13
2.9.1 Overall Approach 13
2.9.2 The Flow Spec Structure 14
3. SERVICE PROVIDER INTERFACE REFERENCE 15
3.1 Socket Routines 15
3.1.1 WSPBind() 16
3.1.2 WSPCloseSocket() 18
3.1.3 WSPGetPeerName() 19
3.1.4 WSPGetSockName() 20
3.1.5 WSPGetSockOpt() 22
3.1.6 WSPIoctlSocket() 27
3.1.7 WSPListen() 29
3.1.8 WSPSelect() 31
3.1.9 WSPSetSockOpt() 34
3.1.10 WSPShutdown() 38
3.1.11 WSPAccept() 40
3.1.12 WSPAsyncSelect32() 43
3.1.13 WSPCallbackSelect16() 49
3.1.14 WSPCancelBlockingCall32() 55
3.1.15 WSPCleanup() 57
3.1.16 WSPConnect() 59
3.1.17 WSPEnumNetworkEvents() 64
3.1.18 WSPEventSelect() 66
3.1.19 WSPIsBlocking32() 71
3.1.20 WSPRecv() 72
3.1.21 WSPRecvFrom() 75
3.1.22 WSPSend() 78
3.1.23 WSPSendTo() 81
3.1.24 WSPSetBlockingHook32() 85
3.1.25 WSPSocket() 87
3.1.26 WSPStartup() 89
3.1.27 WSPUnhookBlockingHook32() 93
4. Upcalls 94
4.1 WPUCreateSocketHandle() 95
4.2 WPUCloseSocketHandle() 96
4.3 WPUQuerySocketHandleContext() 97
4.4 WPUSetSocketHandleContext() 98
4.5 WPUQueueUserAPC32() 99
4.6 WPUGetCurrentThreadId32() 100
5. Installation APIs 101
5.1 WPUInstallProvider() 101
5.2 WPUDeinstallProvider() 102
Appendix A. Error Codes and Header Files 103
A.1 Error Codes 103
A.2 Winsock SPI Header File - ws2spi.h 105
Appendix B. Notes for Winsock Service Providers 120
B.1 Introduction 120
B.2 Winsock SPI Run Time Components 120
B.3 Error Codes 120
Appendix C. Outstanding Issues 121
.
{General comments: This is really coming along and you guys
(I assume Keith in particular) have really done some nice
work. The most important thing we need to fix (which I think
must be done before the 12th) is to get the service provider
model established correctly. See my comments in section
2.2.1.2 for details. Other than that, my corrections which
are sprinkled liberally throughout the document are mostly
minor issues. Note that I did suggest appending `32' onto
the names of WSPSelect() as well as a few others. Also, I
would really like to thin down the opens section some so
that we don't distract the larger group onto what are
essentially DLL implementationimplemenation issues. See my
comments at the end of the doc for details.
Sooner or later we are going to have to do a very thorough
and careful editing job on this document so that it always
speaks from the perspective of a service provider interface
spec as opposed to an application programming interface
perspective. I realize that the PII SPI had all of these
same problems, but we still have to fix this. In many places
it is quite obvious that we just did a cut and paste from
the API spec without really fixing all the text
appropriately. This does not need to be done by the 12th,
but we need to nail down a reasonable date by which we will
do this. }
1. INTRODUCTION
This document defines the Service Provider Interface (SPI)
of Windows Socket (Winsock) 2.0. The Winsock SPI specifies
the external interface of a service provider to be
implemented by vendors of network protocol stacks.
Installing a service provider allows Windows applications
written to the Winsock 2 API interface to access the service
provider'scorresponding network protocol stacks. This will
permit one or more applications to have access to multiple
protocol stacks simultaneously.
1.1 Winsock Specification is a WOSA Component
The Winsock network transport services are provided as a
WOSA (Windows Open Services Architecture) component. They
consist of both an application programming interface (API)
used by applications and a service provider interface (SPI)
implemented by service providers. This document is designed
to be a stand-alone reference for Winsock service provider
developers. Readers intending to write network applications
should refer to the document "Windows Socket Interface,
revision 2.0" which describes Winsock 2 API.
Windows Open Service Architecture (WOSA) provides a single-
level interface for connecting front-end applications with
back-end services. The front-end application and back-end
service need not speak each other's language in order to
communicate as long as they both know how to talk to the
WOSA interface. As a result, WOSA allows application
developers and vendors of back-end services to mix and match
applications and services to build solutions that shield
programmers and users from the underlying complexity of the
system. WOSA defines an abstraction layer to heterogeneous
computing resources through the WOSA set of APIs. Because
this set of APIs is extensible, new services and their
corresponding APIs can be added as needed. Applications
written to the WOSA APIs have access not only to all the
various computing environments supported today, but also to
all additional environments as they become available.
Moreover, applications don't have to be modified in any way
to enjoy this support.
Each service recognized by WOSA also has a set of interfaces
that service-provider vendors use to take advantage of the
seamless interoperability that WOSA provides. In order to
provide transparent access for applications, each
implementation of a particular WOSA service simply needs to
support the functions defined by its service-provider
interface.
WOSA uses a Windows dynamic-link library (DLL) that allows
software components to be linked at runtime. In this way,
applications are able to connect to services dynamically. An
application needs to know only the definition of the
interface, not its implementation.
1.1.1 Winsock 2 DLLs
Winsock network services follow the WOSA model. This means
that there exists a Winsock Application Programming
Interface (API), which is the application programmer's
access to network services, a Winsock Service Provider
Interface (SPI) which is implemented by network service
provider vendors, and the Winsock DLL. For 16 bit
applications this DLL is referred to as (WINSOCK2.DLL for 16-
bit applications, while 32 bit applications use WSOCK32.DLL
for 32-bit applications). Note that in Windows 3
environments, only Winsock2.DLL will be available, while
Windows 95 and Windows NT support both DLLs. Winsock 2's
WOSA compliant architecture is illustrated below in See
Figure 111Figure 1Figure 1.
Figure 111
1.2 Microsoft Windows and Windows-specific extensions
This SPI is intended to be usable within all implementations
and versions of Microsoft Windows including Windows NT,
Windows 95, Windows 3.11, and Windows 3.1.
Winsock makes provisions for multithreaded Windows
processes. In the non-preemptive Win16 environment, a task
corresponds to a process with a single thread of execution.
In the preemptive Win32 environment, a process contains one
or more threads of execution.
The Microsoft Windows extensions included in PII are
provided to allow application developers to create software
which conforms to the Windows programming model. It is
expected that this will facilitate the creation of robust
and high-performance applications, and will improve the
cooperative multitasking of applications within non-
preemptive versions of Windows. With the exception of
PSStartup() and PSCleanup() their use is not mandatory.
1.3 Naming Conventions
The Winsock SPI uses the same naming conventions for
functions, messages, and parameters as those used by the
Winsock API except that all the functions are prefixed by
WSP, which stands for Winsock Service Provider.
SPI functions applicable only specific to a particular
platform end in an identifying suffix. For example,
WSPCallbackSelect16() is applicable only specific to 16-bit
Windows, and WSPAsyncSelect32() is applicable onlyspecific
to 32-bit Windows.
"Upcalls" (utility functions made available by the Winsock
DLL for use by SPI DLLs and installation programs) are
prefixedprevixed by WPU, which stands for Winsock Provider
Upcall.
2. OVERVIEW
2.1 Configuration of Winsock Service Providers
When a service provider is installed, some configuration
information must be added to a configuration database to
give the Winsock DLL required information regarding the
service provider. A service provider vendor must arrange for
this information to be updated as part of the service
provider installation.
Under Windows NT and Windows 95, this configuration
information is stored in the system registry. Under Windows
3.1 and 3.11, this configuration information is stored in
the WINSOCK2.INI file.
2.1.1 Registry Layout for Windows NT and Windows 95
All provider configuration information is stored under the
following registry key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Win
sock2
Throughout this document, all references to relative subkeys
and values are assumed to exist under this main Winsock2
registry key. For example, any reference to the "Providers"
subkey is actually a reference to the
"HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Winsock
2\Providers" key.
2.1.1.1 Providers
The "Providers" subkey contains one subkey for each
installed service provider. The maximum length of provider
subkey names is 32 characters. These subkeys are created by
any software that installs service providers.
The "ProviderOrder" subkey contains zero or more values used
to locate the active service providers. These values also
establish a priority ordering of service providers. The name
of each value represents an active service provider. For
example:
\ProviderOrder
Microsoft TCP/IP = REG_SZ ""
novlwp = REG_SZ ""
TC&S = REG_SZ ""
2.1.1.2 Provider-specific Keys
{ This section needs some additional thought. PII's view of
the world was that there was some number of service
providers, each of which supported exactly one address
family and one or more different socket types. (PII
basically ignored the protocol value, since it was almost
always specified as zero .) It was generally assumed that
each socket type corresponded to a different protocol (e.g.
UDP vs.vs TCP), but that all of the different protocols or
socket types were supplied by the single DLL referenced in
the provider section. Thus for PII, a standard TCP/IP stack
would show up as one provider that supported two different
socket types (SOCK_STREAM and SOCK_DGRAM).
The WS2 view of the world is that each service provider
encompasses exactly one protocol which is uniquely
identified by its protocol value. I believe there needs to
be a 1:1 mapping between service provider entries and
PROTOCOL_INFO structs returned by WSAEnumProtocols(). As
such we need to make sure that all of the information needed
to create the PROTOCOL_INFO structs appear in the service
provider entries (registry or INI file as appropriate).
Since each service provider entry corresponds to a single
protocol, it naturally supports a single address family as
well. However, in the case of a multi-behaviored protocol
like SPX, there may be more than one possible socket type
value that can be used. It is this socket type value which a
service provider would use to determine which of the
available behaviors an application desires. Thus for
example, a standard TCP/IP stack would show up as two
service providers: one for the UDP protocol and one for the
TCP protocol, even though both such providers refer to the
same service provider DLL.
The descriptions in this section assume the PII model of
service providers which is, I believe, at variance with the
proposed Winsock 2 model. It is very important that we are
all on the same page here and that the SPI document clearly
describes how this works.
Each Winsock service provider must have a unique subkey
under the "Providers" subkey. It is the responsibility of
the service provider to create its provider-specific subkey
at the time it is installed. It is also the responsibility
of the service provider to delete its provider-specific
subkey at the time it is removed. Only the service provider
writes values in its provider-specific subkey. The Winsock
DLL reads only the following values in the provider-specific
subkey. Other values in the subkey are permitted for
internal use by the service provider. This subkey consists,
at a minimum, of the following:
\Provider\<Provider Name>
ProviderFilename = REG_SZ "<filename>"
ProviderDescription = REG_SZ "<Description of the
provider>"
ProviderDomain = REG_DWORD <Address family>
ProviderAddrLength = REG_DWORD <length>
NumSockets = REG_DWORD <count> { PII model implied }
SocketType<index> = REG_DWORD <Socket Type>
AddressFamily<index> = REG_DWORD <Address Family>
Protocol<index> = REG_DWORD <Protocol>
MinimumAddressLength<index> = REG_DWORD <Minimum
Address Length>
MaximumAddressLength<index> = REG_DWORD <Maximum
Address Length>
ProtocolAttributes<index> = REG_DWORD <Protocol
Attributes>
ProtocolSocketDescription<index> = REG_SZ "<Description
of the protocolsocket>"
For example:
\Provider\novlwp
ProviderFilename = REG_SZ "novlwp.WPSP"
ProviderDescription = REG_SZ "Novell LAN WorkPlace for
DOS"
ProviderDomain = REG_DWORD 2
ProviderAddrLength = REG_DWORD 8
NumSockets = REG_DWORD 3
SocketType0 = REG_DWORD 1
AddressFamily0 = REG_DWORD 2
Protocol0 = REG_DWORD 2
MinimumAddressLength0 = REG_DWORD 16
MaximumAddressLength0 = REG_DWORD 16
ProtocolAttributes0 = REG_DWORD 0x00001066
ProtocolSocketDescription0 = REG_SZ "Stream socket in
INET domain"
SocketType1 = REG_DWORD 2
AddressFamily1 = REG_DWORD 2
Protocol1 = REG_DWORD 2
MinimumAddressLength1 = REG_DWORD 16
MaximumAddressLength1 = REG_DWORD 16
ProtocolAttributes1 = REG_DWORD 0x00001609
ProtocolSocketDescription1 = REG_DSZ "Dgram socket in
INET domain"
SocketType2 = REG_DWORD 3
AddressFamily2 = REG_DWORD 2
Protocol2 = REG_DWORD 2
MinimumAddressLength2 = REG_DWORD 16
MaximumAddressLength2 = REG_DWORD 16
ProtocolAttributes2 = REG_DWORD 0x00000109
ProtocolSocketDescription2 = REG_SZ"Raw socket in INET
domain"
The ProviderFilename value identifies the filename of the
service provider DLL.
The ProviderDescription value is the descriptive text of
this service provider.
The ProviderDomain value specifies the address family
(defined in "ws2spi.h") this provider works with.
The ProviderAddrLength value is the (maximum) length of
addresses (in bytes) used in the address family specified in
ProviderDomain. The length includes the two-byte address
family and the size of the address family specific address.
The NumSockets value indicates how many different types of
sockets are supported, and how many SocketType<index>,
AddressFamily<index>, Protocol<index>, and
ProtocolSocketDescription<index> values appear in the
section.
The SocketType<index> value (one per socket type) identifies
the type of this socket as defined in "ws2spi.h".
The AddressFamily<index> value (one per socket type)
identifies the address family of this socket as defined in
"ws2spi.h".
The Protocol<index> value (one per socket type) identifies
the protocol of this socket as defined in "ws2spi.h".
The MinimumAddressLength<index> value (one per socket type)
specifies the minimum BYTE size of a valid address for this
protocol.
The MaximumAddressLength<index> value (one per socket type)
specifies the maximum BYTE size of a valid address for this
protocol.
The ProtocolAttributes<index> value (one per socket type)
identifies the behavioral characteristics of the protocol.
This value consists of any number of XP_xxx values ORed
together. (The XP_xxx values are defined in the Registration
and Resolution API specification.)
The ProtocolSocketDescription<index> value (one per socket
type) is the descriptive text for this protocolsocket.
In the SocketType<index>, AddressFamily<index>,
Protocol<index>, and ProtocolSocketDescription<index>
values, <index> takes the values from 0 to one less than
<count> (as specified in NumSockets). These values are
created by any software that installs the service provider.
Although all these values must be present, there is no
requirement that they appear in numerical order.
The service provider may include any other values/subkeys in
its subkey which are necessary to fulfill the
responsibilities of the provider as specified in the Winsock
Service Provider Interface Specification, or for other
private configuration purposes.
2.1.2 WINSOCK2.INI Layout for Windows 3.1
The WINSOCK2.INI file contains a wide variety of
information, and two kinds of identifiers are used:
1. name-sequence numbers. These numbers simply provide a
convenient way to index through a list of similar entries in
a WINSOCK2.INI file section. For example, the list of
"ProviderKey" entries in the [Providers] section uses the
names ProviderKey0, ProviderKey1, ProviderKey2, ... as a set
of easily-indexed names for the entries. The scope of these
name-sequence numbers is strictly limited to the section in
which they appear. These numbers are unrelated to anything
outside the section. They may be completely renumbered
whenever the WINSOCK2.INI configuration changes.
2. permanent string identifiers. These strings are
permanent identifiers for entries. They typically appear in
several different WINSOCK2.INI file sections to identify a
relationship between entries in those two sections. For
example, each provider-specific section ([Provider-<Provider
key>]) includes the permanent string identifier called
"provider key" of the provider in the section name. This
indicates that the entry corresponds to the service provider
with the matching permanent string identifier in the
[Providers] section. The scope of these string identifiers
includes the entire WINSOCK2.INI and persists until such
identifiers are explicitly changed. Some of these
identifiers can be retrieved through the Winsock SPI
interface.
2.1.2.1 Providers
The "[Providers]" section of WINSOCK2.INI specifies the
total number of the installed Winsock service providers, and
the provider key for each service provider. This information
is used so that Winsock2.DLL can identify and load each
provider.
These entries in this section have the following format:
[Providers]
NumProviders=<count>
ProviderKey<index>="<Provider Key>"
For example:
[Providers]
NumProviders=2
ProviderKey0="novlwp"
ProviderKey1="FTP"
The NumProviders entry indicates how many service providers
are installed, and how many ProviderKey<index> entries
appear in the section. <count> is set to 0 when the Winsock
implementation is initialized; the values are subsequently
updated by any software that installs or removes service
providers.
Each ProviderKey<index> entry (one per provider) specifies
an unique provider key with which the service provider can
identify itself. <index> takes the values from 0 to one less
than <count> (as specified in NumProviders). The maximum
length of the provider key is 32 characters. These entries
are created by any software that installs service providers,
and must be renumbered as providers are deleted. Although
all these entries must be present, there is no requirement
that they appear in numerical order. This provider key is
also used to link parameters in other sections for provider-
specific information.
2.1.2.2 Provider-specific Sections ([Provider-<Provider
Key>])
For each Winsock service provider defined in the [Providers]
section, there must be a [Provider-<Provider Key>] section.
The <Provider Key> value is the provider key defined for
that service provider in the corresponding
ProviderKey<index>="<Provider Key>" entry in the [Providers]
section. For example, corresponding to an entry such as
ProviderKey0="novlwp" there would be a section named
[Provider-novlwp].
It is the responsibility of the service provider to create
its provider-specific section in WINSOCK2.INI at the time it
is installed. It is also the responsibility of the service
provider to delete its provider-specific section in
WINSOCK2.INI at the time it is removed. Only the service
provider writes entries in its provider-specific section.
Winsock2.DLL reads only the following entries in the
provider-specific section. Other entries in the section are
permitted for internal use by the service provider. This
section consists, at a minimum, of the following:
[Provider-<Provider Key>]
ProviderFilename="<filename>"
ProviderDescription="<Description of the provider>"
ProviderDomain=<Address family>
ProviderAddrLength=<length>
NumSockets=<count>
SocketType<index>=<Socket Type>
AddressFamily<index>=<Address Family>
Protocol<index>=<Protocol>
MinimumAddressLength<index>=<Minimum Address Length>
MaximumAddressLength<index>=<Maximum Address Length>
ProtocolAttributes<index>=<Protocol Attributes>
ProtocolSocketDescription<index>="<Description of the
protocolsocket>"
For example:
[Provider-novlwp]
ProviderFilename="novlwp.WPSP"
ProviderDescription="Novell LAN WorkPlace for DOS"
ProviderDomain=2
ProviderAddrLength=8
NumSockets=3
SocketType0=1
AddressFamily0=2
Protocol0=2
MinimumAddressLength0 = 16
MaximumAddressLength0 = 16
ProtocolAttributes0 = 0x00001066
ProtocolSocketDescription0="Stream socket in INET
domain"
SocketType1=2
SocketDescription1="Dgram socket in INET domain"
SocketType2=3
MinimumAddressLength0 = 16
MaximumAddressLength0 = 16
ProtocolAttributes0 = 0x00001609
ProtocolSocketDescription2="Raw socket in INET domain"
The ProviderFilename entry identifies the filename of the
service provider DLL.
The ProviderDescription entry is the descriptive text of
this service provider.
The ProviderDomain entry specifies the address family
(defined in "ws2spi.h") this provider works with.
The ProviderAddrLength entry is the (maximum) length of
addresses (in bytes) used in the address family specified in
ProviderDomain. The length includes the two-byte address
family and the size of the address family specific address.
The NumSockets entry indicates how many different types of
sockets are supported, and how many SocketType<index>,
AddressFamily<index>, Protocol<index>, and
ProtocolSocketDescription<index> entries appear in the
section.
The SocketType<index> entry (one per socket type) identifies
the type of this socket as defined in "ws2spi.h".
The AddressFamily<index> entry (one per socket type)
identifies the address family of this socket as defined in
"ws2spi.h".
The Protocol<index> entry (one per socket type) identifies
the protocol of this socket as defined in "ws2spi.h".
The MinimumAddressLength<index> value (one per socket type)
specifies the minimum BYTE size of a valid address for this
protocol.
The MaximumAddressLength<index> value (one per socket type)
specifies the maximum BYTE size of a valid address for this
protocol.
The ProtocolAttributes<index> value (one per socket type)
identifies the behavioral characteristics of the protocol.
This value consists of any number of XP_xxx values ORed
together. (The XP_xxx values are defined in the Registration
and Resolution API specification.)
{Do we need to add a protocol entry as well so that all
three components of the socket() call are represented?}
Absolutely, yes. The omission is a PII artifact. We need
every thing that goes into a PROTOCOL_INFO structstrct since
the DLL implements WSAEnumProtocols() without help from the
service provider itself. In fact, the service provider's DLL
may well not have been loaded yet when WSAEnumProviers() is
invoked, and we certainly do not want to requirereqire it to
be loaded just to implement this function.
The ProtocolSocketDescription<index> entry (one per socket
type) is the descriptive text for this protocolsocket.
In the SocketType<index>, AddressFamily<index>,
Protocol<index>, and ProtocolSocketDescription<index>
entiries, <index> takes the values from 0 to one less than
<count> (as specified in NumSockets). These entries are
created by any software that installs the service provider.
Although all these entries must be present, there is no
requirement that they appear in numerical order.
The service provider may include any other entries in its
section which are necessary to fulfill the responsibilities
of the provider as specified in the Winsock Service Provider
Interface Specification, or for other private configuration
purposes.
2.2. Service Providers Interface Model
Winsock service providers are DLLs with EXPORTED procedure
entry points for the functions defined by the SPI. Service
providers should have their file extension changed from
".DLL" to ".WSP". This requirement is not strict. A service
provider will still operate with the Winsock DLL with any
file extension.
The SPI defines an entry point for each Winsock-specific
function. These procedures are EXPORTED procedures just as
in any DLL. They must be exported by ordinal numbers, as
defined in "ws2spi.h" for each function. The Winsock DLL
calls these Winsock specific entry points once the service
provider is loaded using the standard dynamic linkage
mechanism for calling DLLs.
Although entry points are required to be EXPORTED by name,
loading entry points by name is time-consuming in some
Windows environments. The SPI includes a function to
retrieve an entire table of SPI entry points, bypassing the
name-oriented entry point loading. The PII.DLL has the
option of using PSGetProcTable() to load entry points in
environments where this is a useful optimization.
PSGetProcTable() retrieves all the functions defined by the
SPI.
The entry points described above cover the instances in
which the Winsock DLL invokes functions provided by the
service provider. The SPI also defines several circumstances
in which the service provider calls back into the Winsock
DLL to inform the Winsock DLL of varioussome occurrences.
2.3 Initialization of Winsock Service Providers
Over time, different versions may exist for the Winsock
DLLs, applications, and service providers. New versions may
define new features, new fields to data structures and bit
fields, etc. Version numbers therefore indicate how to
interpret various data structures.
To allow optimal mixing and matching of different versions
of applications, versions of the Winsock DLL itself, and
versions of service providers by different vendors, the SPI
provides a version negotiation mechanism for the Winsock DLL
and the service provider. This version negotiation is
handled by WSPStartup(). Basically, the Winsock DLL passes
to the service provider the highest version numbers it is
compatible with. The service provider compares this with its
own supported range of version numbers. If these ranges
overlap, the service provider returns a value within the
overlapping portion of the range as the result of the
negotiation. Usually, this should be the highest possible
value. If the ranges do not overlap, the two parties are
incompatible and the function returns an error.
2.4 Functionality Implemented WithinValue Added by the
Winsock DLL
The major task that the Winsock DLL does is to serve as a
sort of "traffic manager" between service providers and
applications. Consider several different service providers
interacting with the same application. Each Provider
interacts strictly with the Winsock DLL. The Winsock DLL
takes care of merging streams of events from those service
providers into a single stream directed at the application.
It hides the details of arbitration and synchronization over
the data structures holding this single stream. Service
providers are unaware that any of this is happening. They do
not need to be concerned about the details of cooperating
with one another or even the existence of other service
providers. By abstracting the service providers into a
consistent DLL interface, the Winsock DLL can interact with
a variety of providers regardless of the underlying
protocol's implementation technology.
In addition to its major "traffic manager" service, the
Winsock DLL provides a number of other services such as
socket descriptor management (in order to avoid conflicts
and ambiguities between applications and service providers
in order to avoid conflict and among service providers),
parameter validation for Winsock API and Winsock SPI,
version negotiation between applications and the Winsock
DLL, as well as between the Winsock DLL and service
providers. The Winsock DLL also realizes protocol
enumeration, event objects, the shared sockets,
implementation and and the pseudo blocking mechanism for
Windows 3 environments.for any blocking Winsock function
calls. Note that the differences between 16 and 32 bit
versions of Windows with respect to blocking, preemption and
shared address spaces dictates that the mechanisms used to
implement the 16 and 32 bit versions of Winsock 2 DLLs vary
significantly as well. This in turn leads to certain SPI
functions that are applicable only to either 16 or 32 bit
Windows implementations.
{It would be worthwhile to describe the routineg mechanism
here. I.e., when an application invokes a socket-based API
(such as bind()) how does the Winsock DLL route this request
to the appropriate service provider?}
{ I agree that providing a simple example at this point would
be most helpful }
2.5 Functionality ImplementedValue Added by Service
Providers
The Winsock DLL has no knowledge about how requests to
service providers are realized; this is up to the service
provider implementation. Service providers implement the
actual transport protocol which includes such functions as
support the low-level network-specific aspects of Winsock.
This includes functions such as setting up connections,
transferring data, exercising flow control and error
control, etc. The implementation of such functions may
differs greatly from one provider to another. Service
providers hide the implementation-specific details of how
network operations are accomplished.
To summarize: service providers implement provide the low-
level network-specific protocolsmechanisms. The Winsock DLL
provides the medium-level traffic management that
interconnects these transport protocols mechanisms with
applications. Applications in turn provide the policy of how
these traffic streams and network-specific operations are
used to accomplish the functions desired by the user.
2.6 Differences and Similarities Between Winsock API and SPI
The Winsock SPI is similar to the Winsock API in that all
the basic socket functions appear. Support functions like
htonl(), htons(), ntohl(), ntohs(), inet_addr(), and
inet_ntoa() are implemented in the Winsock DLL, and are not
passed down to SPI.
If an extended version of a function and the original
version of a function both exist in the API, only the
extended version will show up in the SPI. For example,
connect() and WSAConnect() will both map to WSPConnect(),
accept() and WSAAccept() to WSPAccept(), and socket() and
WSASocket() to WSPSocket().
Since error codes are returned along with SPI functions,
equivalents of WSAGetLastError() and WSASetLastError() are
not needed in the SPI.
Shared sockets, socket group member enumeration, and Winsock
service provider enumeration are bothall realized in the
Winsock DLL, thus WSADuplicateSocket(), WSAEnumGroup(), and
WSAEnumProtocolsProviders() do not appear as SPI functions.
2.7 Differences Between 32-bit and 16-bit Winsock SPI
In 32-bit environments the service providers are responsible
for implementing blocking behavior. All blocking hook
related API functions such as WSAIsBlocking(),
WSACancelBlockingCall(), WSASetBlockingHook(), and
WSAUnhookBlockingHook() appear in SPI. All event object
related API functions are implemented as #define macros,
mapping the Winsock event functions to native Win32 event
functions.
In 16-bit environments the Winsock DLL implements all
blocking behavior (as pseudopsuedo blocking), and all SPI
sockets are strictly non-blocking. All the blocking hook
related API functions such as WSAIsBlocking(),
WSACancelBlockingCall(), WSASetBlockingHook(), and
WSAUnhookBlockingHook() dowill not appear in the 16 bit SPI
because the blocking hook implementation iswill be realized
in Winsock2.DLL. Similarly, all the event object related API
functions are also implemented in Winsock2.DLL, e.g.,
WSACreateEvent(), WSACloseEvent(), WSASetEvent(),
WSAResetEvent(), WSAWaitForMultipleEvents(), and
WSAGetOverlappedResult().
2.8 Sockets 2.8 Sockets
See API spec for intorductory text on sockets.
2.8.1 Socket Types
See the API for information on socket types.
2.8.21 Out-of-band data
Note: The following discussion of out-of-band data, also
referred to as TCP Urgent data, follows the model used in
the Berkeley software distribution. Users and implementors
should be aware of the fact that there are at present two
conflicting interpretations of RFC 793 (in which the concept
is introduced), and that the implementation of out-of-band
data in the Berkeley Software Distribution does not conform
to the Host Requirements laid down in RFC 1122. To minimize
interoperability problems, applications writers are advised
not to use out-of-band data unless this is required in order
to interoperate with an existing service. Winsock suppliers
are urged to document the out-of-band semantics (BSD or RFC
1122) which their product implements. It is beyond the scope
of this specification to mandate a particular set of
semantics for out-of-band data handling.
Note that the out-of-band data functionality is mainly
inherited from the TCP/IP world, and may not be available to
other communication domains supported by this specification.
The stream socket abstraction includes the notion of "out of
band'' data. Out-of-band data is a logically independent
transmission channel associated with each pair of connected
stream sockets. Out-of-band data is delivered to the user
independently of normal data. The abstraction defines that
the out-of-band data facilities must support the reliable
delivery of at least one out-of-band message at a time. This
message may contain at least one byte of data, and at least
one message may be pending delivery to the user at any one
time. For communications protocols which support only in-
band signaling (i.e., the urgent data is delivered in
sequence with the normal data), the system normally extracts
the data from the normal data stream and stores it
separately. This allows users to choose between receiving
the urgent data in order and receiving it out of sequence
without having to buffer all the intervening data. It is
possible to "peek'' at out-of-band data.
An application may prefer to process out-of-band data "in-
line", as part of the normal data stream. This is achieved
by setting the socket option SO_OOBINLINE (see section
3.1.3.1.3.1., WSPSetSockOptWSPsetsockopt()). In this case,
the application may wish to determine whether any of the
unread data is "urgent" (the term usually applied to in-line
out-of-band data). To facilitate this, the Winsock service
provider will maintain a logical "mark" in the data stream
to indicate the point at which the out-of-band data was
sent. An application can use the SIOCATMARK
WSPIoctlSocketWSPioctlsocket() command (see section
3.1.63.1.63.1.6) to determine whether there is any unread
data preceding the mark. For example, it might use this to
resynchronize with its peer by ensuring that all data up to
the mark in the data stream is discarded when appropriate.
2.8.3 Broadcasting
See the API spec for information on Winsock 2's support for
broadcasting
2.8.42 Socket Options
The socket options supported by Winsock SPI are listed and
described in the pages describing
WSPSetSockOptWSPsetsockopt() and
WSPGetSockOptWSPgetsockopt(). A summary of the available
options and the default value for each is shown in the
following table.
Value Type Meaning Default Not
e
SO_ACCEPTCONN BOOL Socket is FALSE get
WSPListenWSPliste unless a onl
n()ing. WSPListenW y
SPlisten()
has been
performed
SO_BROADCAST BOOL Socket is FALSE (i)
configured for
the transmission
of broadcast
messages.
SO_DEBUG BOOL Debugging is FALSE (i)
enabled.
SO_DONTLINGER BOOL If true, the TRUE
SO_LINGER option
is disabled.
SO_DONTROUTE BOOL Routing is FALSE (i)
disabled.
SO_FLOWSPEC char The flow spec of NULL get
FAR * this socket. onl
y
SO_GROUP_FLOWSP char The flow spec of NULL get
EC FAR * the socket group onl
to which this y
socket belongs.
SO_GROUP_ID GROUP The identifier of NULL get
the group to onl
which this socket y
belongs.
SO_GROUP_PRIORI int The relative 0 (i)
TY priority for
sockets that are
part of a socket
group.
SO_KEEPALIVE BOOL Keepalives are FALSE (i)
being sent.
SO_LINGER struct Returns the l_onoff is
linger current linger 0
options.
SO_MAX_MSGDG_SI unsign Maximum size of a Implementa get
ZE ed int message for tion onl
message-oriented dependent y
socket types
(e.g. DGRAM and
DSTREAM). Has no
meaning for
stream-oriented
sockets.
SO_OOBINLINE BOOL Out-of-band data FALSE
is being received
in the normal
data stream.
SO_PROTOCOL_INF struct Description of Protocol get
O PROTOC protocol info for dependent onl
OL_INF protocol that is y
O bound to this
socket.
SO_RCVBUF int Buffer size for Implementa (i)
receives tion
dependent
SO_REUSEADDR BOOL The address to FALSE
which this socket
is bound can be
used by others.
SO_SNDBUF int Buffer size for Implementa (i)
sends tion
dependent
SO_TYPE int The type of the As created get
socket (e.g. via onl
SOCK_STREAM). WSPSsocket y
()
PVD_CONFIG char An opaque data Implementa
FAR * structure object tion
containing dependent
configuration
information of
the service
provider.
TCP_NODELAY BOOL Disables the Implementa
Nagle algorithm tion
for send dependent
coalescing.
Notes:
(i) An implementation may silently ignore this option
on WSPSetSockOptWSPsetsockopt() and return a
constant value for WSPGetSockOptWSPgetsockopt(),
or it may accept a value for
WSPSetSockOptWSPsetsockopt() and return the
corresponding value in
WSPGetSockOptWSPgetsockopt() without using the
value in any way.
2.9 Quality of Service (QOS)
2.9.1 Overall Approach
The basic QOS mechanism in Winsock descends from the flow
specification (or "flow spec") as described by Craig
Partridge in RFC 1363, dated September 1992. A brief
overview of this concept is as follows:
Flow specs describe a set of characteristics about a
proposed connection-oriented, unidirectional flow through
the network. An application may associate a pair of flow
specs with a socket at the time a connection request is
made. Flow specs indicate parametrically what level of
service is required and also stipulate whether the
application is willing to be flexible if the requested level
of service is not available. After a connection is
established, the application may retrieve the flow specs
associated with the socket and examine the contents to
discover the level of service that the network is willing
and/or able to provide. If the service provided is not
acceptable, the application may close the socket and take
whatever action is appropriate (e.g. scale back and ask for
a lower quality of service, try again later, notify the user
and exit, etc.)
Even after a flow is established, conditions in the network
may change resulting in a reduction (or increase) in the
available service level. A notification mechanism is
included which utilizes the usual Winsock 2 notification
techniques to indicate to the application that QOS levels
have changed. The app should again retrieve the
corresponding flow specs and examine them in order to
discover what aspect of the service level has changed.
The flow specs proposed for Winsock 2 divide QOS
characteristics into the following general areas:
1.Network bandwidth utilization - The manner in which the
application's traffic will be injected into the network.
This includes specifications for average bandwidth
utilization, peak bandwidth, and maximum burst duration.
2.Latency - Upper limits on the amount of delay and delay
variation that are acceptable.
3.Level of service guarantee - Whether or not an absolute
guarantee is required as opposed to best effort. Note
that providers which have no feasible way to provide the
level of service requestedrequeted are expected to fail
the connection attempt.
4.Cost - This is a place holder for a future time when a
meaningful cost metric can be determined.
5.Provider-specific parameters - The flow spec itself can
be extended in ways that are particular to specific
providers, and the assumed provider can be identified.
An application indicates its desire for a non-default flow
spec at the time a connection request is made (see
WSPConnect () and WSPAccept()). Since establishing a flow
spec'd connection is likely to involve cooperation and/or
negotiation between intermediate routers and hosts, the
results of a flow spec request cannot be determined until
after the connection operation is fully completed. After
this time, the application may use getsockopt() to retrieve
the resulting flow spec structure so that it can determine
what the network was willing and/or able to supply.
2.9.2 The Flow Spec Structure
The Winsock 2 flow spec structure is defined in Winsock2.h
and is reproduced here.
typedef enum
{
GuaranteedService,
BestEffortService
} GUARANTEE;
typedef struct _flowparams
{
int64 AverageBandwith;// In Bytes/sec
int64 PeakBandwidth; // In Bytes/sec
int64 BurstLength; // In microseconds
int64 Latency; // In microseconds
int64 DelayVariation;// In microseconds
GUARANTEE levelOfGuarantee;// Guaranteed or
// Best Effort
int32 CostOfCall; // Reserved for future
// use, must be set to 0
int32 ProviderId; // Provider Identifier
int32 SizePSP; // Length of provider
// specific parameters
UCHAR ProviderSpecificParams[1];// provider
specific //
parameters
} FLOWPARAMS;
typedef struct _QualityOfService
{
FLOWPARAMS ForwardFP; // Caller(Initiator) to
callee
FLOWPARAMS BackwardFP; // Callee to caller
} QOS, FAR * LPQOS;
3. SERVICE PROVIDER INTERFACE REFERENCE
3.1 Socket Routines
This chapter presents the service provider socket library
routines in alphabetical order, and describes each routine
in detail.
{ Since the SPI is new, I propose that we do not have
separate sections for Windows-specific extensions}
In each routine it is indicated that the header file
ws2spi.h must be included. Appendix A.2 lists the Berkeley-
compatible header files which are supported. These are
provided for compatibility purposes only, and each of them
will simply include PII.h. The Windows header file windows.h
is also needed, but ws2spi.h will include it if necessary.
3.1.1 PSaccept()
Description Accept a connection on a socket.
#include <PIISPI.h>
SOCKET PASCAL FAR PSaccept ( SOCKET s, struct
sockaddr FAR * addr,
int FAR * addrlen, int FAR * lpErrno );
s A descriptor identifying a socket which
is listening for connections after a
PSlisten().
addr An optional pointer to a buffer which
receives the address of the connecting
entity, as known to the communications
layer. The exact format of the addr
argument is determined by the address
family established when the socket was
created.
addrlen An optional pointer to an integer which
contains the length of the address addr.
lpErrno A pointer to the error code.
Remarks This routine extracts the first connection on the
queue of pending connections on s, creates a new
socket with the same properties as s except not in
the listening state, and returns a handle to the
new socket. If no pending connections are present
on the queue, and the socket is not marked as non-
blocking, PSaccept() blocks the caller until a
connection is present. If the socket is marked
non-blocking and no pending connections are
present on the queue, PSaccept() returns an error
as described below. The accepted socket may not
be used to accept more connections. The original
socket remains open.
The argument addr is a result parameter that is
filled in with the address of the connecting
entity, as known to the communications layer. The
exact format of the addr parameter is determined
by the address family in which the communication
is occurring. The addrlen is a value-result
parameter; it should initially contain the amount
of space pointed to by addr; on return it will
contain the actual length (in bytes) of the
address returned. This call is used with
connection-oriented socket types such as
SOCK_STREAM. If addr and/or addrlen are equal to
NULL, then no information about the remote address
of the accepted socket is returned.
Return Value If no error occurs, PSaccept() returns a
value of type SOCKET which is a descriptor for the
accepted packet. Otherwise, a value of
INVALID_SOCKET is returned, and a specific error
code is available in lpErrno.
The integer referred to by addrlen initially
contains the amount of space pointed to by addr.
On return it will contain the actual length in
bytes of the address returned.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT The addrlen argument is too
small (less than the sizeof a
struct sockaddr).
WSAEINTR The (blocking) call was
canceled via
PSCancelBlockingCall().
WSAEINPROGRESS A blocking PII call is in
progress.
WSAEINVAL PSlisten() was not invoked
prior to PSaccept().
WSAEMFILE The queue is non-empty upon
entry to PSaccept() and there
are no descriptors available.
WSAENOBUFS No buffer space is available.
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP The referenced socket is not a
type that supports connection-
oriented service.
WSAEWOULDBLOCK No connections are present to
be accepted.
See Also PSbind(), PSconnect(), PSlisten(), PSselect(),
PSsocket(), PSCallbackSelect()
3.1.1 WSPBindWSPbind()
Description Associate a local address with a socket.
#include <ws2spi.h>
int WSPAPI WSPBindWSPbind ( SOCKET s, const struct
sockaddr FAR * name, int namelen, int FAR *
lpErrno );
s A descriptor identifying an unbound
socket.
name The address to assign to the socket. The
sockaddr structure is defined as
follows:
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
namelen The length of the name.
lpErrno A pointer to the error code.
Remarks This routine is used on an unconnected
connectionless or connection-oriented socket,
before subsequent WSPConnect()s or
WSPListenWSPlisten()s. When a socket is created
with WSPsocket(), it exists in a name space
(address family), but it has no name assigned.
WSPBindWSPbind() establishes the local association
of the socket by assigning a local name to an
unnamed socket.
As an example, in the Internet address family, a
name consists of three parts: the address family,
a host address, and a port number which identifies
the application. In Winsock 2, the name parameter
is not strictly interpreted as a pointer to a
"sockaddr" struct. It is cast this way for Windows
Sockets 1.1 compatibility. Service providers are
free to regard it as a pointer to a block of
memory of size namelen. The first two bytes in
this block (corresponding to "sa_family" in the
"sockaddr" declaration) must contain the address
family that was used to create the socket.
Otherwise an error WSAEFAULT will occur.
Return Value If no error occurs, WSPBindWSPbind() returns
0. Otherwise, it returns SOCKET_ERROR, and a
specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEADDRINUSE The specified address is
already in use. (See the
SO_REUSEADDR socket option
under
WSPSetSockOptWSPsetsockopt().)
WSAEFAULT The namelen argument is too
small (less than the size of a
struct sockaddr), the name
argument contains incorrect
address format for the
associated address family, or
the first two bytes of the
memory block specified by name
does not match the address
family associate with the
socket descriptor s.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEAFNOSUPPORT The specified address family
is not supported by this
protocol.
WSAEINVAL The socket is already bound to
an address.
WSAENOBUFS Not enough buffers available,
too many connections.
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPConnect(), WSPListenWSPlisten(),
WSPGetSockNameWSPgetsockname(),
WSPSetSockOptWSPsetsockopt(), WSPsocket(),
PSCancelBlockingCall().
3.1.2 WSPCloseSocketWSPclosesocket()
Description Close a socket.
#include <ws2spi.h>
int WSPAPI WSPCloseSocketWSPclosesocket ( SOCKET
s, int FAR * lpErrno );
s A descriptor identifying a socket.
lpErrno A pointer to the error code.
Remarks This function closes a socket. More precisely, it
releases the socket descriptor s, so that further
references to s will fail with the error
WSAENOTSOCK. If this is the last reference to an
underlying socket, the associated naming
information and queued data are discarded.
The semantics of WSPCloseSocketWSPclosesocket()
are affected by the socket options SO_LINGER and
SO_DONTLINGER as follows:
Option Interval Type of close Wait
for close?
SO_DONTLINGER Don't care Graceful No
SO_LINGER Zero Hard No
SO_LINGER Non-zero Graceful Yes
If SO_LINGER is set (i.e. the l_onoff field of the
linger structure is non-zero; see sections
3.1.53.1.53.1.5 and 3.1.3.1.3.1.) with a zero
timeout interval (l_linger is zero),
WSPCloseSocketWSPclosesocket() is not blocked even
if queued data has not yet been sent or
acknowledged. This is called a "hard" or
"abortive" close, because the socket's virtual
circuit is reset immediately, and any unsent data
is lost. Any WSPRecvWSPrecv() call on the remote
side of the circuit will fail with WSAECONNRESET.
If SO_LINGER is set with a non-zero timeout
interval, the PSclosesocket() call blocks until
the remaining data has been sent or until the
timeout expires. This is called a graceful
disconnect. Note that if the socket is set to non-
blocking and SO_LINGER is set to a non-zero
timeout, the call to PSclosesocket() will fail
with an error of WSAEWOULDBLOCK.
If SO_DONTLINGER is set on a stream socket (i.e.
the l_onoff field of the linger structure is zero;
see sections 3.1.53.1.53.1.5 and 3.1.3.1.3.1.),
the WSPCloseSocketWSPclosesocket() call will
return immediately. However, any data queued for
transmission will be sent if possible before the
underlying socket is closed. This is also called a
graceful disconnect. Note that in this case the
Winsock service provider may not release the
socket and other resources for an arbitrary
period, which may affect applications which expect
to use all available sockets.
Return Value If no error occurs,
WSPCloseSocketWSPclosesocket() returns 0.
Otherwise, a value of SOCKET_ERROR is returned,
and a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPAccept, WSPsocket(),
WSPIoctlSocketWSPioctlsocket(),
WSPSetSockOptWSPsetsockopt().
3.1.4 PSconnect()
Description Establish a connection to a peer.
#include <PIISPI.h>
int PASCAL FAR PSconnect ( SOCKET s, const struct
sockaddr FAR * name,
int namelen, int FAR * lpErrno );
s A descriptor identifying an unconnected
socket.
name The name of the peer to which the socket
is to be connected.
namelen The length of the name.
lpErrno A pointer to the error code.
Remarks This function is used to create a connection to
the specified destination. For connection-
oriented sockets (e.g., type SOCK_STREAM), an
active connection is initiated to the foreign host
using name (an address in the name space of the
socket; for a detailed description, please see
PSbind()). When the socket call completes
successfully, the socket is ready to send/receive
data.
For a connectionless socket (e.g., type
SOCK_UNREL_DGRAM), the operation performed by
PSconnect() is merely to establish a default
destination address which will be used on
subsequent PSsend() and PSrecv() calls.
If the socket, s, is unbound, unique values are
assigned to the local association by the system,
and the socket is marked as bound. Note that if
the address field of the name structure is all
zeroes, PSconnect() will return the error
WSAEADDRNOTAVAIL.
Return Value If no error occurs, PSconnect() returns 0.
Otherwise, it returns SOCKET_ERROR, and a specific
error code is available in lpErrno.
On a non-blocking socket,If the return value is
SOCKET_ERROR an application should call
PSGetLastError(). For connection-oriented
sockets, if the return value is 0, indicating the
connect operation has been successfully initiated,
then your application can either:
1. Use PSselect() to determine the completion of
the connection request by checking if the socket
is writeable, or
2. If your application is using PSCallbackSelect()
to indicate interest in connection events, then
your application will receive an FD_CONNECT
callback when the connect operation is complete.
Error Codes The following errors may occur at the time of
the function call, and indicate that the connect
operation could not be initiated.
WSANOTINITIALISED A successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEADDRINUSE The specified address is
already in use.
WSAEINTR The (blocking) call was
canceled via
PSCancelBlockingCall().
WSAEINPROGRESS A blocking PII call is in
progress.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAEDESTADDREQ A destination address is
required.
WSAEFAULT The namelen argument is
incorrect.
WSAEINVAL The socket is not already
bound to an address.
WSAEISCONN The socket is already
connected.
WSAEMFILE No more socket descriptors are
available.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAENOTSOCK The descriptor is not a
socket.
WSAEWOULDBLOCK The socket is marked as non-
blocking and the connection
cannot be completed
immediately. It is possible
to PSselect() the socket while
it is connecting by
PSselect()ing it for writing.
The following error codes may be set when the
callback function is invoked.
WSANOTINITIALISED A successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEADDRINUSE The specified address is
already in use.
WSAEINTR The (blocking) call was
canceled via
PSCancelBlockingCall().
WSAEINPROGRESS A blocking PII call is in
progress.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAECONNREFUSED The attempt to connect was
forcefully rejected.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAETIMEDOUT Attempt to connect timed out
without establishing a
connection
See Also PSaccept(), PSbind(), PSgetsockname(), PSsocket(),
PSselect()PSCallbackSelect(), PSConnectEx().
3.1.3 WSPGetPeerNameWSPgetpeername()
Description Get the address of the peer to which a socket
is connected.
#include <ws2spi.h>
int WSPAPI WSPGetPeerNameWSPgetpeername ( SOCKET
s, struct sockaddr FAR * name, int FAR * namelen,
int FAR * lpErrno );
s A descriptor identifying a connected
socket.
name The structure which is to receive the
name of the peer.
namelen A pointer to the size of the name
structure.
lpErrno A pointer to the error code.
Remarks WSPGetPeerNameWSPPSgetpeername() retrieves the
name of the peer connected to the socket s and
stores it in the struct sockaddr identified by
name. It is used on a connected datagram or stream
socket.
On return, the namelen argument contains the
actual size of the name returned in bytes.
Return Value If no error occurs,
WSPGetPeerNameWSPgetpeername() returns 0.
Otherwise, a value of SOCKET_ERROR is returned,
and a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT The namelen argument is not
large enough.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOTCONN The socket is not connected.
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPBindWSPPSbind(), WSPsocket(),
WSPGetSockNameWSPgetsockname().
3.1.4 WSPGetSockNameWSPgetsockname()
Description Get the local name for a socket.
#include <ws2spi.h>
int WSPAPI WSPGetSockNameWSPgetsockname ( SOCKET
s, struct sockaddr FAR * name,
int FAR * namelen, int FAR * lpErrno );
s A descriptor identifying a bound socket.
name Receives the address (name) of the
socket.
namelen The size of the name buffer.
lpErrno A pointer to the error code.
Remarks WSPGetSockNameWSPPSgetsockname() retrieves the
current name for the specified socket descriptor
in name. It is used on a bound and/or connected
socket specified by the s parameter. The local
association is returned. This call is especially
useful when a WSPConnect() call has been made
without doing a WSPBindWSPbind() first; as this
call provides the only means by which the local
association which has been set by the service
provider can be determinedyou can determine the
local association which has been set by the
system.
On return, the namelen argument contains the
actual size of the name returned in bytes.
If a socket was bound to an unspecified address
(e.g., ADDR_ANY), indicating that any of the
host's addresses within the specified address
family should be used for the socket,
WSPGetSockNameWSPgetsockname() will not
necessarily return information about the host
address, unless the socket has been connected with
WSPConnect() or WSPAccept. The Winsock DLL must
not assume that the address will be specified
unless the socket is connected. This is because
for a multi-homed host the address that will be
used for the socket is unknown unless the socket
is connected.
Return Value If no error occurs,
WSPGetSockNameWSPgetsockname() returns 0.
Otherwise, a value of SOCKET_ERROR is returned,
and a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT The namelen argument is not
large enough, or the name or
namelen argument is not part
of the user address space.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOTSOCK The descriptor is not a
socket.
WSAEINVAL The socket has not been bound
to an address with
WSPBindWSPbind(), or ADDR_ANY
is specified in
WSPBindWSPbind() but
connection has not yet occurs.
See Also WSPBindWSPPSbind(), WSPsocket(),
WSPGetPeerNameWSPgetpeername().
3.1.5 WSPGetSockOptWSPgetsockopt()
Description Retrieve a socket option.
#include <ws2spi.h>
int WSPAPI WSPGetSockOptWSPgetsockopt ( SOCKET s,
int level, int optname,
char FAR * optval, int FAR * optlen, int FAR *
lpErrno );
s A descriptor identifying a socket.
level The level at which the option is
defined; the only supported levels are
SOL_SOCKET and SOL_PROVIDER.
(SOL_PROVIDER is defined to be an alias
for IPPROTO_TCP for the sake of
compatibility with Windows Sockets
specification 1.1.)
optname The socket option for which the value is
to be retrieved.
optval A pointer to the buffer in which the
value for the requested option is to be
returned.
optlen A pointer to the size of the optval
buffer.
lpErrno A pointer to the error code.
Remarks WSPGetSockOptWSPPSgetsockopt() retrieves the
current value for a socket option associated with
a socket of any type, in any state, and stores the
result in optval. Options may exist at multiple
protocol levels, but they are always present at
the uppermost "socket'' level. Options affect
socket operations, such as whether an operation
blocks or not, the routing of packets, out-of-band
data transfer, etc.
The value associated with the selected option is
returned in the buffer optval. The integer pointed
to by optlen should originally contain the size of
this buffer; on return, it will be set to the size
of the value returned. For SO_LINGER, this will be
the size of a struct linger; for most other
options it will be the size of an integer.
The Winsock DLL is responsible for allocating any
memory space pointed to directly or indirectly by
any of the parameters it specifiesd.
If the option was never set with
WSPSetSockOptWSPsetsockopt(), then
WSPGetSockOptWSPgetsockopt() returns the default
value for the option.
level = SOL_SOCKET
Value Type Meaning
SO_ACCEPTCONN BOOL Socket is
WSPListenWSPlisten()ing.
SO_BROADCAST BOOL Socket is configured for
the transmission of
broadcast messages.
SO_DEBUG BOOL Debugging is enabled.
SO_DONTLINGER BOOL If true, the SO_LINGER
option is disabled.
SO_DONTROUTE BOOL Routing is disabled.
SO_FLOWSPEC char The flow spec of this
FAR * socket.
SO_GROUP_FLOWSPEC char The flow spec of the
FAR * socket group to which this
socket belongs.
SO_GROUP_ID GROUP The identifier of the
group to which this socket
belongs.
SO_GROUP_PRIORITY int The relative priority for
sockets that are part of a
socket group.
SO_KEEPALIVE BOOL Keepalives are being sent.
SO_LINGER struct Returns the current linger
linger options.
SO_MAX_MSGDG_SIZE unsigne Maximum size of a message
d int for message-oriented
socket types (e.g. DGRAM
and DSTREAM). Has no
meaning for stream-
oriented sockets.
SO_OOBINLINE BOOL Out-of-band data is being
received in the normal
data stream.
SO_PROTOCOL_INFO struct Description of protocol
PROTOCO info for protocol that is
L_INFO bound to this socket.
SO_RCVBUF int Buffer size for receives
SO_REUSEADDR BOOL The socket may be bound to
an address which is
already in use.
SO_SNDBUF int Buffer size for sends
SO_TYPE int The type of the socket
(e.g. SOCK_STREAM).
level = SOL_PROVIDER
(also aliased to IPPROTO_TCP)
PVD_CONFIG Service An "opaque" data structure
Provide object from the service
r provider associated with
Depende socket s. This object
nt stores the current
configuration information
of the service provider.
The exact format of this
data structure is service
provider specific.
TCP_NODELAY BOOL Disables the Nagle
algorithm for send
coalescing.
BSD options not supported for
WSPGetSockOptWSPgetsockopt() are:
Value Type Meaning
SO_ERROR int Get error status and clear
SO_RCVLOWAT int Receive low water mark
SO_RCVTIMEO int Receive timeout
SO_SNDLOWAT int Send low water mark
SO_SNDTIMEO int Send timeout
IP_OPTIONS Get options in IP header.
TCP_MAXSEG int Get TCP maximum segment
size.
Calling WSPGetSockOptWSPgetsockopt() with an
unsupported option will result in an error code of
WSAENOPROTOOPT being returned in lpErrno.
SO_DEBUG
Winsock service providers are encouraged (but not
required) to supply output debug information if
the SO_DEBUG option is set by an application. The
mechanism for generating the debug information and
the form it takes are beyond the scope of this
specification.
SO_FLOWSPEC
This is a get-only socket option which indicates
the flow spec of the socket. The default flow spec
defined in Sec. 2.8.3 will be returned before the
application sets the flow spec for this socket.
The WSAENOPROTOOPT error code is indicated for
service providers which do not support the flow
spec option. See WSPConnect() about how to set the
flow spec.
SO_GROUP_FLOWSPEC
This is a get-only socket option which indicates
the flow spec of the group this socket belongs to.
The default flow spec defined in Sec. 2.8.3 will
be returned before the application sets the flow
spec for this socket group. The WSAENOPROTOOPT
error code is indicated for service providers
which do not support the group flow spec option.
If this socket does not belong to an appropriate
socket group, the Flen and Blen fields of the
returned QOS struct are set to 0. See WSPConnect()
about how to set the flow spec.
SO_GROUP_ID
This is a get-only socket option which indicates
the identifier of the group this socket belongs
to. If this socket is not a group socket, the
value is NULL.
The group option is provided as a way to
facilitate the formation of multiplex
relationships between two or more sockets (each
with the group option set) that will share an
underlying physical connection. While such
multiplexing is an assumed attribute of packet
switched networks, the assumption does not
necessarily hold true for circuit switched
networks. By setting this option, the application
indicates a preference for eligible sockets to be
multiplexed together.
SO_GROUP_PRIORITY
Group priority indicates the relative priority of
the specified socket relative to other sockets
within the socket group. Values are non-negative
integers, with zero corresponding to the highest
priority. Priority values represent a hint to the
underlying service provider about how potentially
scarce resources should be allocated. For example,
whenever two or more sockets are both ready to
transmit data, the highest priority socket (lowest
value for SO_GROUP_PRIORITY) should be serviced
first, with the remainder serviced in turn
according to their relative priorities.
The WSAENOPROTOOPT error code is indicated for non
group sockets or for service providers which do
not support group sockets.
SO_KEEPALIVE
An application may request that a TCP/IP service
provider enable the use of "keep-alive" packets on
TCP connections by turning on the SO_KEEPALIVE
socket option. A Winsock provider need not support
the use of keep-alives: if it does, the precise
semantics are implementation-specific but should
conform to section 4.2.3.6 of RFC 1122:
Requirements for Internet Hosts -- Communication
Layers. If a connection is dropped as the result
of "keep-alives" the error code WSAENETRESET is
returned to any calls in progress on the socket,
and any subsequent calls will fail with
WSAENOTCONN.
SO_LINGER
SO_LINGER controls the action taken when unsent
data is queued on a socket and a
WSPCloseSocketWSPclosesocket() is performed. See
WSPCloseSocketWSPclosesocket() for a description
of the way in which the SO_LINGER settings affect
the semantics of WSPCloseSocketWSPclosesocket().
The application gets the desired behavior by
creating a struct linger (pointed to by the optval
argument) with the following elements:
struct linger {
int l_onoff;
int l_linger;
}
To enable SO_LINGER, the application should set
l_onoff to a non-zero value, set l_linger to 0 or
the desired timeout (in seconds), and call
PSsetsockopt(). To enable SO_DONTLINGER (i.e.
disable SO_LINGER) l_onoff should be set to zero
and PSsetsockopt() should be called.
SO_MAX_MSGDG_SIZE
This is a get-only socket option which indicates
the maximum size of a message for message-oriented
socket types (e.g. DGRAM or DSTREAM) as
implemented by a particular service provider. It
has no meaning for byte stream oriented sockets
SO_RESERVED_BW and SO_AVAILABLE_BW
These options are used primarily with isochronous
sockets, although both options have meaningful
interpretations for non-isochronous sockets as
well. When dealing with isochronous sockets, the
application may retrieve the value of
SO_AVAILABLE_BW to determine the maximum amount of
bandwidth that is available to be reserved. It
uses SO_RESERVED_BW to actually request bandwidth
allocation or to determine the current bandwidth
already allocated to the socket. In both
instances, bandwidth values are expressed in "bits
per second (bps)".
For non-isochronous sockets, the value of
SO_AVAILABLE_BW is used to provide a hint as to
the relative capacity of the underlying network.
Applications may wish to know, for example,
whether they are running over a 1200 baud serial
line or a 155 Mbps ATM link. Since in many
instances it is impossible for a non-isochronous
service provider to supply a precise value for
this option, applications must realize that the
supplied value may represent nothing more than a
reasonable approximation of the capacity of the
underlying network. Applications may likewise use
the value of SO_RESERVED_BW to provide a hint to
the service provider about the desired amount of
bandwidth.
SO_REUSEADDR
By default, a socket may not be bound (see
WSPBindWSPbind()) to a local address which is
already in use. On occasions, however, it may be
desirable to "re-use" an address in this way.
Since every connection is uniquely identified by
the combination of local and remote addresses,
there is no problem with having two sockets bound
to the same local address as long as the remote
addresses are different. To inform the Winsock
provider that a WSPBindWSPbind() on a socket
should not be disallowed because the desired
address is already in use by another socket, the
application should set the SO_REUSEADDR socket
option for the socket before issuing the
WSPBindWSPbind(). Note that the option is
interpreted only at the time of the
WSPBindWSPbind(): it is therefore unnecessary (but
harmless) to set the option on a socket which is
not to be bound to an existing address, and
setting or resetting the option after the
WSPBindWSPbind() has no effect on this or any
other socket.
PVD_CALL_ID
This is a get-only socket option which corresponds
to an opaque Winsock call ID used for
Winsock/Telephony Integration. See Appendix C for
details. Winsock service providers which are not
also TAPI service providers should return an
WSAENOPROTOOPT error code when this option's value
is requested.
PVD_CONFIG
This option retrieves an "opaque" data structure
object from the service provider associated with
socket s. This object stores the current
configuration information of the service provider.
The exact format of this data structure is service
provider specific.
TCP_NODELAY
The TCP_NODELAY option disables the Nagle
algorithm. The Nagle algorithm is used to reduce
the number of small packets sent by a host by
buffering unacknowledged send data until a full-
size packet can be sent. However, for some
applications this algorithm can impede
performance, and TCP_NODELAY may be used to turn
it off. Application writers should not set
TCP_NODELAY unless the impact of doing so is well-
understood and desired, since setting TCP_NODELAY
can have a significant negative impact of network
performance.
TAPI_DEVICE_ID
This is a get-only socket option which corresponds
to a line device ID for Windows Telephony API
(TAPI). See Appendix C for details. Winsock
service providers which are not also TAPI service
providers should return an WSAENOPROTOOPT error
code when this option's value is requested.
Return Value If no error occurs,
WSPGetSockOptWSPgetsockopt() returns 0. Otherwise,
a value of SOCKET_ERROR is returned, and a
specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT The optlen argument was
invalid.
WSAEINVAL No value available for optname
at the moment.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOPROTOOPT The option is unknown or
unsupported by the indicated
protocol family.
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPSetSockOptWSPPSsetsockopt(),WSPsocket().
3.1.6 WSPIoctlSocketWSPioctlsocket()
Description Control the mode of a socket.
#include <ws2spi.h>
int WSPAPI WSPIoctlSocketWSPioctlsocket ( SOCKET
s, long cmd, u_long FAR * argp,
int FAR * lpErrno );
s A descriptor identifying a socket.
cmd The command to perform on the socket s.
argp A pointer to a parameter for cmd.
lpErrno A pointer to the error code.
Remarks This routine may be used on any socket in any
state. It is used to get or retrieve operating
parameters associated with the socket, independent
of the protocol and communications subsystem. The
following commands are supported:
Command Semantics
FIONBIO Enable or disable non-blocking mode on
the socket s. argp points at an
unsigned long, which is non-zero if non-
blocking mode is to be enabled and zero
if it is to be disabled. When a socket
is created, it operates in blocking mode
(i.e. non-blocking mode is disabled).
This is consistent with BSD sockets.
The PSCallbackSelect() routine
automatically sets a socket to
nonblocking mode. If PSCallbackSelect()
has been issued on a socket, then any
attempt to use PSioctlsocket() to set
the socket back to blocking mode will
fail with WSAEINVAL. To set the socket
back to blocking mode, an application
must first disable PSCallbackSelect() by
calling PSCallbackSelect() with the
lEvent parameter equal to 0.
FIONREAD Determine the amount of data which can
be read atomically from socket s. argp
points at an unsigned long in which
WSPIoctlSocketWSPioctlsocket() stores
the result. If s is stream-oriented
(e.g., type SOCK_STREAM), FIONREAD
returns the total amount of data which
may be read in a single
WSPRecvWSPrecv(); this is normally the
same as the total amount of data queued
on the socket. If s is message-oriented
(e.g., type SOCK_DGRAM), FIONREAD
returns the size of the first datagram
(message) queued on the socket.
SIOCATMARK Determine whether or not all out-of-
band data has been read. This applies
only to a socket of stream style (e.g.,
type SOCK_STREAM) which has been
configured for in-line reception of any
out-of-band data (SO_OOBINLINE). If no
out-of-band data is waiting to be read,
the operation returns TRUE. Otherwise it
returns FALSE, and the next
WSPRecvWSPrecv() or
WSPRecvFromWSPrecvfrom() performed on
the socket will retrieve some or all of
the data preceding the "mark"; the
application should use the SIOCATMARK
operation to determine whether any
remains. If there is any normal data
preceding the "urgent" (out of band)
data, it will be received in order.
(Note that a WSPRecvWSPrecv() or
WSPRecvFromWSPrecvfrom() will never mix
out-of-band and normal data in the same
call.) argp points at a BOOL in which
WSPIoctlSocketWSPioctlsocket() stores
the result.
Compatibility This function is a subset of ioctl() as used
in Berkeley sockets. In particular, there is no
command which is equivalent to FIOASYNC, while
SIOCATMARK is the only socket-level command which
is supported.
{where should we break the news about not allowing any new
ioctls to be introduced? }
{Not here. This is more of a charter/requirements issue for
the API extension group.}
Return Value Upon successful completion, the
WSPIoctlSocketWSPioctlsocket() returns 0.
Otherwise, a value of SOCKET_ERROR is returned,
and a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEINVAL cmd is not a valid command, or
argp is not an acceptable
parameter for cmd, or the
command is not applicable to
the type of socket supplied
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOTSOCK The descriptor s is not a
socket.
See Also WSPPSsocket(), WSPSetSockOptWSPsetsockopt(),
WSPGetSockOptWSPgetsockopt().
3.1.7 WSPListenWSPlisten()
Description Establish a socket to listen for incoming
connection.
#include <ws2spi.h>
int WSPAPI WSPListenWSPlisten ( SOCKET s, int
backlog, int FAR * lpErrno );
s A descriptor identifying a bound,
unconnected socket.
backlog The maximum length to which the queue of
pending connections may grow.
lpErrno A pointer to the error code.
Remarks To accept connections, a socket is first created
with WSPsocket(), a backlog for incoming
connections is specified with
WSPListenWSPlisten(), and then the connections are
accepted with WSPAccept. WSPListenWSPlisten()
applies only to sockets that are connection-
oriented (, e.g., those of type SOCK_STREAM). The
socket s is put into "passive'' mode where
incoming connections are acknowledged and queued
pending acceptance by the process.
This function is typically used by servers that
could have more than one connection request at a
time: if a connection request arrives with the
queue full, the client will receive an error with
an indication of WSAECONNREFUSED.
PSlisten() attempts to continue to function
rationally when there are no available
descriptors. It will accept connections until the
queue is emptied. If descriptors become
available, a later call to PSlisten() or
PSaccept() will re-fill the queue to the current
or most recent "backlog'', if possible, and resume
listening for incoming connections.
Compatibility backlog is currently limited (silently) to
SOMAXCONN, which is defined to be 5 in the header
file. As in 4.3BSD, illegal values (less than 1 or
greater than 5) are replaced by the nearest legal
value.
{Why do we still enforce this? NT limits the
backlog to 100, not 5, because BIG servers (like
ftp.microsoft.com) often receive periodic floods
of connection requests, easily overrunning a
backlog of 5 connections.}
Return Value If no error occurs, WSPListenWSPlisten()
returns 0. Otherwise, a value of SOCKET_ERROR is
returned, and a specific error code is available
in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEADDRINUSE An attempt has been made to
WSPListenWSPlisten() on an
address in use.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEINVAL The socket has not been bound
with WSPBindWSPbind().
WSAEISCONN The socket is already
connected.
WSAEMFILE No more socket descriptors are
available.
WSAENOBUFS No buffer space is available.
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP The referenced socket is not
of a type that supports the
WSPListenWSPlisten()
operation.
See Also WSPAccept, WSPConnect(), WSPsocket().
3.1.8 WSPSelectWSPselect32()
Description Determine the status of one or more sockets.
#include <ws2spi.h>
int WSPAPI WSPSelectWSPselect32 ( int nfds, fd_set
FAR * readfds, fd_set FAR * writefds, fd_set FAR
* exceptfds, const struct timeval FAR * timeout,
int FAR * lpErrno );
nfds This argument is ignored and included
only for the sake of compatibility.
readfds An optional pointer to a set of sockets
to be checked for readability.
writefds An optional pointer to a set of sockets
to be checked for writability
exceptfds An optional pointer to a set of sockets
to be checked for errors.
timeout The maximum time for PSselect() to wait,
or NULL for blocking operation.This
value istTThis value should be ignored.
(The Winsock DLL will always supply a
value of zero for the sake of
compatability.)The maximum time for
WSPSelect() to wait, or NULL for a
blocking operation. Note that the 16-bit
Winsock DLL will always pass in a
timeout of zero to perform a non-
blocking poll on the socket set(s). The
32-bit Winsock DLL may pass in any
timeout value.
lpErrno A pointer to the error code.
Remarks This function is only applicable to the 32 bit
SPI. The 16 bit Winsock2.DLL uses the
WSPCallbackSelect() function to implement the API
version of select() since blocking may be
requested. WSPSelect32() is used to determine the
status of one or more sockets. For each socket,
the caller may request information on read, write
or error status. The set of sockets for which a
given status is requested is indicated by an
fd_set structure. All entries in an fd_set
correspond to sockets created by the service
provider. Upon return, the structure is updated to
reflect the subset of these sockets which meet the
specified condition, and WSPSelectWSPselect32()
returns the total number of sockets meeting the
conditions. A set of macros is provided for
manipulating an fd_set. These macros are
compatible with those used in the Berkeley
software, but the underlying representation is
completely different.
The parameter readfds identifies those sockets
which are to be checked for readability. If the
socket is currently WSPListenWSPlisten()ing, it
will be marked as readable if an incoming
connection request has been received, so that an
WSPAccept is guaranteed to complete immediately.
For other sockets, readability means that queued
data is available for reading or, for connection-
oriented sockets, that the virtual circuit
corresponding to the socket has been closed, so
that a WSPRecvWSPrecv() or
WSPRecvFromWSPrecvfrom() is guaranteed to complete
immediately. If the virtual circuit was closed
gracefully, then a WSPRecvWSPrecv() will return
immediately with 0 bytes read; if the virtual
circuit was reset, then a WSPRecvWSPrecv() will
complete immediately with the error code
WSAECONNRESET. The presence of out-of-band data
will be checked if the socket option SO_OOBINLINE
has been enabled (see
WSPSetSockOptWSPsetsockopt()).
The parameter writefds identifies those sockets
which are to be checked for writability. If a
socket is WSPConnect()ing, writability means that
the connection establishment successfully
completed. If the socket is not in the process of
WSPConnect()ing, writability means that a
WSPSendWSPsend() or WSPSendToWSPsendto() or
WSAGetBuffer() will complete immediately. [It is
not specified how long this guarantee can be
assumed to be valid, particularly in a
multithreaded environment.]
The parameter exceptfds identifies those sockets
which are to be checked for the presence of out-of-
band data or any exceptional error conditions.
Note that out-of-band data will only be reported
in this way if the option SO_OOBINLINE is FALSE.
For a connection-oriented socket, the breaking of
the connection by the peer or due to KEEPALIVE
failure will be indicated as an exception. This
specification does not define which other errors
will be included. If a socket is WSPConnect()ing,
failure of the connect attempt is indicated in
exceptfds.
Any of readfds, writefds, or exceptfds may be
given as NULL if no descriptors are of interest.
Four macros are defined in the header file
ws2spi.h for manipulating the descriptor sets. The
variable FD_SETSIZE determines the maximum number
of descriptors in a set. (The default value of
FD_SETSIZE is 64, which may be modified by
#defining FD_SETSIZE to another value before
#including ws2spi.h.) Internally, an fd_set is
represented as an array of SOCKETs; the last valid
entry is followed by an element set to
INVALID_SOCKET. The macros are:
FD_CLR(s, *set) Removes the descriptor s
from set.
FD_ISSET(s, *set) Nonzero if s is a member of
the set, zero otherwise.
FD_SET(s, *set) Adds descriptor s to set.
FD_ZERO(*set) Initializes the set to the
NULL set.
The parameter timeout controls how long the
PSselect() may take to complete. If timeout is a
null pointer, PSselect() will block indefinitely
until at least one descriptor meets the specified
criteria. Otherwise, timeout points to a struct
timeval which specifies the maximum time that
PSselect() should wait before returning. If the
timeval is initialized to {0, 0}, PSselect() will
return immediately; this is used to "poll" the
state of the selected sockets. If this is the
case, then the PSselect() call is considered
nonblocking and the standard assumptions for
nonblocking calls apply. For example, the
blocking hook must not be called, and the PII
implementation must not yield.
Return Value WSPPSSelectselect32() returns the total
number of descriptors which are ready and
contained in the fd_set structures, 0 if the time
limit expired, or SOCKET_ERROR if an error
occurred. If the return value is SOCKET_ERROR, a
specific error code is available in lpErrno.
Comments WSPPSSelect 32() has no effect on the
persistencepersistance of socket events registered
with WSPEventSelect().
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this API.
WSAEFAULT The Winsock service provider
was unable to allocated needed
resources for its internal
operations, or the readfds,
writefds, or exceptfds
parameters are not part of the
user address space.
WSAENETDOWN The network subsystem has
failed.
WSAEINVAL The timeout value is not
valid.
WSAEINTR The (blocking) call was
canceled via
WSACancelBlockingCall().
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOTSOCK One of the descriptor sets
contains an entry which is not
a socket.
See Also WSPAccept(), WSPConnect(), WSPRecvWSPrecv(),
WSPRecvFromWSPrecvfrom(), WSPSendWSPsend(),
WSPSendToWSPsendto(), WSPEventSelect()
3.1.9 WSPSetSockOptWSPsetsockopt()
Description Set a socket option.
#include <ws2spi.h>
int WSPAPI WSPSetSockOptWSPsetsockopt ( SOCKET s,
int level, int optname,
const char FAR * optval, int optlen, int FAR *
lpErrno );
s A descriptor identifying a socket.
level The level at which the option is
defined; the only supported levels are
SOL_SOCKET and SOL_PROVIDER.
(SOL_PROVIDER is defined to be an alias
for IPPROTO_TCP for the sake of
compatibility with Windows Sockets
specification 1.1.)
optname The socket option for which the value is
to be set.
optval A pointer to the buffer in which the
value for the requested option is
supplied.
optlen The size of the optval buffer.
lpErrno A pointer to the error code.
Remarks WSPSetSockOptWSPPSsetsockopt() sets the current
value for a socket option associated with a socket
of any type, in any state. Although options may
exist at multiple protocol levels, they are always
present at the uppermost "socket'' level. Options
affect socket operations, such as whether
expedited data is received in the normal data
stream, whether broadcast messages may be sent on
the socket, etc.
There are two types of socket options: Boolean
options that enable or disable a feature or
behavior, and options which require an integer
value or structure. To enable a Boolean option,
optval points to a nonzero integer. To disable the
option optval points to an integer equal to zero.
optlen should be equal to sizeof(int) for Boolean
options. For other options, optval points to the
an integer or structure that contains the desired
value for the option, and optlen is the length of
the integer or structure.
level = SOL_SOCKET
Value Type Meaning
SO_BROADCAST BOOL Allow transmission of
broadcast messages on the
socket.
SO_DEBUG BOOL Record debugging
information.
SO_DONTLINGER BOOL Don't block close waiting
for unsent data to be
sent. Setting this option
is equivalent to setting
SO_LINGER with l_onoff set
to zero.
SO_DONTROUTE BOOL Don't route: send directly
to interface.
SO_GROUP_PRIORITY int Specify the relative
priority to be established
for sockets that are part
of a socket group.
SO_KEEPALIVE BOOL Send keepalives
SO_LINGER struct Linger on close if unsent
linger data is present
SO_OOBINLINE BOOL Receive out-of-band data
in the normal data stream.
SO_RCVBUF int Specify buffer size for
receives
SO_REUSEADDR BOOL Allow the socket to be
bound to an address which
is already in use. (See
bind().)
SO_SNDBUF int Specify buffer size for
sends.
level = SOL_PROVIDER
(aliased to IPPROTO_TCP)
PVD_CONFIG Service This object stores the
Provide configuration information
r for the service provider
Depende associated with socket s.
nt The exact format of this
data structure is service
provider specific.
TCP_NODELAY BOOL Disables the Nagle
algorithm for send
coalescing.
BSD options not supported for
WSPSetSockOptWSPsetsockopt() are:
Value Type Meaning
SO_ACCEPTCONN BOOL Socket is listening
SO_ERROR int Get error status and clear
SO_RCVLOWAT int Receive low water mark
SO_RCVTIMEO int Receive timeout
SO_SNDLOWAT int Send low water mark
SO_SNDTIMEO int Send timeout
SO_TYPE int Type of the socket
IP_OPTIONS Set options field in IP
header.
SO_DEBUG
Winsock service providers are encouraged (but not
required) to supply output debug information if
the SO_DEBUG option is set by an application. The
mechanism for generating the debug information and
the form it takes are beyond the scope of this
specification.
SO_GROUP_PRIORITY
Group priority indicates the relative priority of
the specified socket relative to other sockets
within the socket group. Values are non-negative
integers, with zero corresponding to the highest
priority. Priority values represent a hint to the
underlying service provider about how potentially
scarce resources should be allocated. For example,
whenever two or more sockets are both ready to
transmit data, the highest priority socket (lowest
value for SO_GROUP_PRIORITY) should be serviced
first, with the remainder serviced in turn
according to their relative priorities.
Eligibility for grouping sockets together is based
on the destination address of sockets marked with
the group option. Sockets which share destination
addresses that are identical except for the last
component of the address (e.g. the port number in
the IP address family) are eligible for group
multiplexing. The manner in which multiplexing is
implemented is left up to the service provider.The
WSAENOPROTOOPT error is indicated for non group
sockets or for service providers which do not
support group sockets.
SO_KEEPALIVE
An application may request that a TCP/IP provider
enable the use of "keep-alive" packets on TCP
connections by turning on the SO_KEEPALIVE socket
option. A Winsock provider need not support the
use of keep-alives: if it does, the precise
semantics are implementation-specific but should
conform to section 4.2.3.6 of RFC 1122:
Requirements for Internet Hosts -- Communication
Layers. If a connection is dropped as the result
of "keep-alives" the error code WSAENETRESET is
returned to any calls in progress on the socket,
and any subsequent calls will fail with
WSAENOTCONN.
SO_LINGER
SO_LINGER controls the action taken when unsent
data is queued on a socket and a
WSPCloseSocketWSPclosesocket() is performed. See
WSPCloseSocketWSPclosesocket() for a description
of the way in which the SO_LINGER settings affect
the semantics of WSPCloseSocketWSPclosesocket().
The application sets the desired behavior by
creating a struct linger (pointed to by the optval
argument) with the following elements:
struct linger {
int l_onoff;
int l_linger;
}
To enable SO_LINGER, the application should set
l_onoff to a non-zero value, set l_linger to 0 or
the desired timeout (in seconds), and call
WSPSetSockOptWSPsetsockopt(). To enable
SO_DONTLINGER (i.e. disable SO_LINGER) l_onoff
should be set to zero and
WSPSetSockOptWSPsetsockopt() should be called.
SO_RESERVED_BW and SO_AVAILABLE_BW
These options are used primarily with isochronous
sockets, although both options have meaningful
interpretations for non-isochronous sockets as
well. When dealing with isochronous sockets, the
application may retrieve the value of
SO_AVAILABLE_BW to determine the maximum amount of
bandwidth that is available to be reserved. It
uses SO_RESERVED_BW to actually request bandwidth
allocation or to determine the current bandwidth
already allocated to the socket. In both
instances, bandwidth values are expressed in "bits
per second (bps)".
For non-isochronous sockets, the value of
SO_AVAILABLE_BW is used to provide a hint as to
the relative capacity of the underlying network.
Applications may wish to know, for example,
whether they are running over a 1200 baud serial
line or a 155 Mbps ATM link. Since in many
instances it is impossible for a non-isochronous
service provider to supply a precise value for
this option, applications must realize that the
supplied value may represent nothing more than a
reasonable approximation of the capacity of the
underlying network. Applications may likewise use
the value of SO_RESERVED_BW to provide a hint to
the service provider about the desired amount of
bandwidth.
SO_REUSEADDR
By default, a socket may not be bound (see
WSPBindWSPbind()) to a local address which is
already in use. On occasions, however, it may be
desirable to "re-use" an address in this way.
Since every connection is uniquely identified by
the combination of local and remote addresses,
there is no problem with having two sockets bound
to the same local address as long as the remote
addresses are different. To inform the Winsock
provider that a WSPBindWSPbind() on a socket
should not be disallowed because the desired
address is already in use by another socket, the
application should set the SO_REUSEADDR socket
option for the socket before issuing the
WSPBindWSPbind(). Note that the option is
interpreted only at the time of the
WSPBindWSPbind(): it is therefore unnecessary (but
harmless) to set the option on a socket which is
not to be bound to an existing address, and
setting or resetting the option after the
WSPBindWSPbind() has no effect on this or any
other socket.
PVD_CONFIG
This option specifies an object previously
obtained using getsockopt(). This object stores
the configuration information for the service
provider associated with socket s. The exact
format of this data structure is service provider
specific.
TCP_NODELAY
The TCP_NODELAY option is specific to TCP/IP
service providers. It is used to disable the Nagle
algorithm. The Nagle algorithm is used to reduce
the number of small packets sent by a host by
buffering unacknowledged send data until a full-
size packet can be sent. However, for some
applications this algorithm can impede
performance, and TCP_NODELAY may be used to turn
it off. Application writers should not set
TCP_NODELAY unless the impact of doing so is well-
understood and desired, since setting TCP_NODELAY
can have a significant negative impact of network
performance.
Return Value If no error occurs,
WSPSetSockOptWSPsetsockopt() returns 0. Otherwise,
a value of SOCKET_ERROR is returned, and a
specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT optval is not in a valid part
of the process address space.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEINVAL level is not valid, or the
information in optval is not
valid.
WSAENETRESET Connection has timed out when
SO_KEEPALIVE is set.
WSAENOPROTOOPT The option is unknown or
unsupported for the specified
provider.
WSAENOTCONN Connection has been reset when
SO_KEEPALIVE is set.
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPBindWSPPSbind(), WSPGetSockOptWSPgetsockopt(),
WSPIoctlSocketWSPioctlsocket(), WSPsocket(),
WSPEventSelect().
3.1.10 WSPShutdownWSPshutdown()
Description Disable sends and/or receives on a socket.
#include <ws2spi.h>
int WSPAPI WSPShutdownWSPshutdown ( SOCKET s, int
how, int FAR * lpErrno );
s A descriptor identifying a socket.
how A flag that describes what types of
operation will no longer be allowed.
lpErrno A pointer to the error code.
Remarks WSPShutdownWSPPSshutdown() is used on all types of
sockets to disable reception, transmission, or
both.
If how is SD_RECEIVE, subsequent receives on the
socket will be disallowed. This has no effect on
the lower protocol layers. For TCP, the TCP window
is not changed and incoming data will be accepted
(but not acknowledged) until the window is
exhausted. For UDP, incoming datagrams are
accepted and queued. In no case will an ICMP error
packet be generated.
If how is SD_SEND, subsequent sends on the socket
are disallowed. For TCP sockets, a FIN will be
sent.
Setting how to SD_BOTH disables both sends and
receives as described above.
Note that WSPShutdownWSPshutdown() does not close
the socket, and resources attached to the socket
will not be freed until
WSPCloseSocketWSPclosesocket() is invoked.
Comments WSPShutdownWSPPSshutdown() does not block
regardless of the SO_LINGER setting on the socket.
An application should not rely on being able to re-
use a socket after it has been shut down. In
particular, a Winsock service provider is not
required to support the use of WSPConnect() on
such a socket.
Return Value If no error occurs, WSPShutdownWSPshutdown()
returns 0. Otherwise, a value of SOCKET_ERROR is
returned, and a specific error code is available
in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEINVAL how is not valid, or is not
consistent with the socket
type, e.g., SD_SEND is used
with a UNI_RECV socket type.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAENOTCONN The socket is not connected
(connection-oriented sockets
only).
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPConnect(), WSPsocket().
3.1.15 WSPsocket()
Description Create a socket.
#include <ws2spi.h>
SOCKET PASCAL FAR WSPsocket ( int af, int type,
int protocol, LPSTR lpszProviderKey, int FAR *
lpErrno );
af An address family specification. The
only format currently supported is
PF_INET, which is the ARPA Internet
address format.
type A type specification for the new socket.
protocol A particular protocol to be used with
the socket, or 0 if the caller does not
wish to specify a protocol.
lpszProviderKey A NULL-terminated string
identifying the Winsock service provider
to use. This information is useful to
provider implementations that present
multiple service provider appearances to
Winsock.
lpErrno A pointer to the error code.
Remarks PSsocket() causes a socket descriptor and any
related resources to be allocated and bound to a
specific transport service provider. If a
protocol is not specified (i.e., equal to 0), the
default for the specified socket type is used.
However, the address family may be given as
AF_UNSPEC (unspecified), in which case the
protocol parameter must be specified. The
protocol number to use is particular to the
"communication domain'' in which communication is
to take place. lpszProviderKey uniquely
identifies the required transport service
provider.
All the socket created are in non-blocking mode.
The following type specifications may be supported
(all sockets are bi-directional unless specified
otherwise):
Type Explanation
SOCK_STREAM Alias for
SOCK_REL_STREAM.
SOCK_DGRAM Alias for
SOCK_UNREL_DGRAM.
SOCK_SEQPACKET Alias for
SOCK_REL_DSTREAM.
SOCK_RAW Raw socket.
SOCK_REL_STREAM Connection-oriented
reliable, unduplicated,
sequenced, byte
streamwith an out-of-
band data transmission
mechanism. Uses TCP
for the Internet
address family.
SOCK_REL_DSTREAM Connection-oriented
reliable, unduplicated,
sequenced, message
streamwith an out-of-
band data transmission
mechanism.
SOCK_UNREL_DSTREAM Connection-oriented
unreliable,
unduplicated,
sequenced, message
streamwith an out-of-
band data transmission
mechanism.
SOCK_REL_UNISEND_DSTREAMConnection-oriented,
reliable, one-way (send
only), unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_REL_UNIRECV_DSTREA
M.
SOCK_REL_UNIRECV_DSTREAMConnection-oriented,
reliable, one-way
(receive only),
unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_REL_UNISEND_DSTREA
M.
SOCK_UNREL_UNISEND_DSTREAM Connection-
oriented, unreliable,
one-way (send only),
unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_UNREL_UNIRECV_DSTR
EAM.
SOCK_UNREL_UNIRECV_DSTREAM Connection-
oriented, unreliable,
one-way (receive only),
unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_UNREL_UNISEND_DSTR
EAM.
SOCK_REL_DGRAM Connectionless,
reliable, datagram.
SOCK_UNREL_DGRAM Connectionless,
unreliable, datagram.
SOCK_REL_ISOCH_DSTREAM Connection-oriented
reliable, unduplicated,
sequenced, isochronous,
message streamwith an
out-of-band data
transmission mechanism.
SOCK_UNREL_ISOCH_DSTREAMConnection-oriented
unreliable,
unduplicated,
sequenced, isochronous,
message streamwith an
out-of-band data
transmission mechanism.
SOCK_UNREL_ISOCH_STREAM Connection-oriented
unreliable,
unduplicated,
sequenced, isochronous,
byte streamwith an out-
of-band data
transmission mechanism.
Connection-oriented sockets such as
SOCK_REL_STREAM provide full-duplex connections,
and must be in a connected state before any data
may be sent or received on them. A connection to
another socket is created with a WSPConnect()
call. Once connected, data may be transferred
using WSPsend() and WSPrecv() calls. When a
session has been completed, a WSPclosesocket()
must be performed. Out-of-band data may also be
transmitted as described in send() and received as
described in recv().
The communications protocols used to implement a
reliable, connection-oriented socket ensure that
data is not lost or duplicated. If data for which
the peer protocol has buffer space cannot be
successfully transmitted within a reasonable
length of time, the connection is considered
broken and subsequent calls will fail with the
error code set to WSAETIMEDOUT.
Connectionless, message-oriented sockets allow
sending and receiving of datagrams to and from
arbitrary peers using WSPsendto() and
WSPrecvfrom(). If such a socket is WSPConnect()ed
to a specific peer, datagrams may be send to that
peer using WSPsend() and may be received from
(only) this peer using WSPrecv().
Return Value If no error occurs, WSPsocket() returns a
descriptor referencing the new socket. Otherwise,
a value of INVALID_SOCKET is returned, and a
specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEAFNOSUPPORT The specified address family
is not supported.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEMFILE No more socket descriptors are
available.
WSAENOBUFS No buffer space is available.
The socket cannot be created.
WSAEPROTONOSUPPORT The specified protocol is not
supported.
WSAEPROTOTYPE The specified protocol is the
wrong type for this socket.
WSAESOCKTNOSUPPORT The specified socket type is
not supported in this address
family.
See Also WSPAccept, WSPbind(), WSPConnect(),
WSPgetsockname(), WSPgetsockopt(),
WSPsetsockopt(), WSPlisten(), WSPrecv(),
WSPrecvfrom(), PSselect(), WSPsend(), WSPsendto(),
WSPshutdown(), WSPioctlsocket().
3.21.111 WSPAccept()
Description Conditionally accept a connection based on
the return value of a condition function, and
optionally create and/or join a socket group.
#include <ws2spi.h>
SOCKET WSPAPI WSPAccept ( SOCKET s, struct
sockaddr FAR * addr, int FAR * addrlen,
LPCONDITIONPROC lpfnCondition, DWORD
dwCallbackData,
int FAR * lpAcceptAction,int FAR * lpErrno );
s A descriptor identifying a socket which
is listening for connections after a
WSPListenWSPlisten().
addr An optional pointer to a buffer which
receives the address of the connecting
entity, as known to the communications
layer. The exact format of the addr
argument is determined by the address
family established when the socket was
created.
addrlen An optional pointer to an integer which
contains the length of the address addr.
lpfnCondition The address of the optional, the
Winsock DLL-supplied condition function
which will make an accept/reject
decision based on the caller information
passed in as parameters, and optionally
create and/or join a socket group by
assigning appropriate value to the
result parameter g of this function.
dwCallbackData The callback data passed back to
the Winsock DLL in the condition
function. This object is not interpreted
by the service providerWinsock
implementation.
lpAcceptAction A optional pointer to the action
taken by the condition function.
lpErrno A pointer to the error code.
Remarks This routine extracts the first connection on the
queue of pending connections on s, and checks it
against the condition function, provided the
condition function is specified (i.e., not NULL).
If lpfnCondition is set to NULL, a connection is
accepted unconditionally, and no socket group is
created or joined. If the condition function
returns CF_ACCEPT, this routine creates a new
socket with the same properties as s and returns a
handle to the new socket, and then optionally
creates and/or joins a socket group based on the
value of the result parameter g in the condition
function. If the condition function returns
CF_REJECT, this routine rejects this connection
request. The condition function runs in the same
thread as this routine does, and should return as
soon as possible. If the decision cannot be made
immediately, the condition function willshould
return CF_DEFER to indicate that no decision has
been made, and no action about this connection
request should be taken by the service provider.
When the Winsock DLL is ready to take action on
the connection request, it may invoke WSPAccept()
again and return either CF_ACCEPT or CF_REJECT as
a return value from the condition function.
If no pending connections are present on the
queue, and the socket is not marked as non-
blocking, PSAcceptEx() blocks the caller until a
connection is present. If the socket is marked
non-blocking and no pending connections are
present on the queue, WSPAccept() returns an error
as described below. The accepted socket may not be
used to accept more connections. The original
socket remains open.
The argument addr is a result parameter that is
filled in with the address of the connecting
entity, as known to the communications layer. The
exact format of the addr parameter is determined
by the address family in which the communication
is occurring. The addrlen is a value-result
parameter; it should initially contain the amount
of space pointed to by addr; on return it will
contain the actual length (in bytes) of the
address returned. This call is used with
connection-oriented socket types such as
SOCK_STREAM. If addr and/or addrlen are equal to
NULL, then no information about the remote address
of the accepted socket is returned. Otherwise,
these two parameters will be filled in regardless
of whether the condition function is specified or
what it returns.
The prototype of the condition function is as
follows:
int WSACALLBACK ConditionFunc( SOCKET s,
LPWSABUF lpCallerId, LPWSABUF lpCallerData,
LPWSABUF lpCalleeId, LPWSABUF lpCalleeData, GROUP
FAR * g, DWORD dwCallbackData );
LPWSABUF is defined in ws2spi.h as follows:
typedef struct _WSABUF {
int len; // the length of the
buffer
char FAR * buf; // the pointer to
the buffer
} WSABUF, FAR * LPWSABUF;
ConditionFunc is a placeholder for athe Winsock
DLL supplied function pointername. The actual
condition function must reside in a DLL or
application module and be exported in the module
definition file. You must use MakeProcInstance()
to get a procedure-instance address for the
callback function.It is invoked in the same thread
as WSPAccept(), thus no other Winsock functions
can be called. The s parameter is the socket
descriptor of the listening socket specified in
PSAcceptEx(). The lpCallerId and lpCallerData are
value parameters which contain the address of the
connecting entity and any user data that was sent
along with the connection request, respectively.
The lpCalleeId is a value parameter which contains
the local address of the connected entity. The
lpCalleeData is a result parameter in which the
condition function fills in the user data passed
back to the connecting entity. lpCalleeData->len
initially contains the length of the buffer
allocated by the service provider, and 0 means
user data back to the caller is not supported. If
lpCalleeData->len is set to 0, no user data will
be passed back. The exact format of the address
and user data is specific to the address family to
which the socket belongs.
The result parameter g is assigned within the
condition function to indicate the following
actions:
if g is an existing socket group id, add s to
this group, provided all the
requirements set by this group are met; or
if g = SG_UNCONSTRAINED_GROUP, create an
unconstrained socket group and have
s as the first member; or
if g = SG_CONSTRAINED_GROUP, create a
constrained socket group and have s as
the first member; or
if g = NULL, no operation is performed.
For unconstrained groups, any set of sockets may
be grouped together as long as they are supported
by a single Winsock service provider and are
connection-oriented. A constrained socket group
requires that connections on all grouped sockets
be to the same host. For newly created socket
groups, the new group id can be retrieved by
lpGroupAction or using
WSPGetSockOptWSPgetsockopt() with option
SO_GROUP_ID, if this operation completes
successfully.
The lpAcceptAction is a result parameter which
contains the action taken by the condition
function, i.e., CF_ACCEPT, CF_REJECT, or CF_DEFER,
if this function returns successfully. If
lpAcceptAction is set to NULL before calling this
function, no information will be passed back.
Return Value If no error occurs, WSPAccept() returns a
value of type SOCKET which is a descriptor for the
accepted socket. Otherwise, a value of
INVALID_SOCKET is returned, and a specific error
code is available in lpErrno.
The integer referred to by addrlen initially
contains the amount of space pointed to by addr.
On return it will contain the actual length in
bytes of the address returned.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this API.
WSAENETDOWN The network subsystem has
failed.
WSAECONNREFUSED The connection request was
forcefully rejected as
indicated in the return value
of the condition function
(CF_REJECT).
WSAEFAULT The addrlen argument is too
small (less than the sizeof a
struct sockaddr) or the
lpfnCondition is not part of
the user address space.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEINVAL WSPListenWSPlisten() was not
invoked prior to WSPAccept(),
parameter g specified in the
condition function is not a
valid value, the return value
of the condition function is
not a valid one, or any case
where the specified socket is
in an invalid state.
WSAEMFILE The queue is non-empty upon
entry to WSPAccept() and there
are no socket descriptors
available.
WSAENOBUFS No buffer space is available.
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP The referenced socket is not a
type that supports connection-
oriented service.
WSATRY_AGAIN The acceptance of the
connection request was
deferred as indicated in the
return value of the condition
function (CF_DEFER).
WSAEWOULDBLOCK No connections are present to
be accepted, or the connection
request that was deferred has
timed out or been withdrawn.
See Also WSPAccept(), WSPBindWSPbind(), WSPConnect(),
WSPGetSockOptWSPgetsockopt(),
WSPListenWSPlisten(), WSPSelectWSPselect(),
WSPsocket(), WSPEventSelect().
3.1.2.12 WSPAsyncSelect32()
Description Request event notification for a socket.
{For obvious reasons, this function description is
particularly bad about sounding like an API function
description instead of an SPI function description }
#include <ws2spi.h>
int WSPAPI WSPAsyncSelect32 ( SOCKET s, HWND hWnd,
unsigned int wMsg, long lEvent, int FAR * lpErrno
);
s A descriptor identifying the socket for
which event notification is required.
hWnd A handle identifying the window which
should receive a message when a network
event occurs.
wMsg The message to be received when a
network event occurs.
lEvent A bitmask which specifies a combination
of network events in which the
application is interested.
lpErrno A pointer to the error code.
Remarks This function is only applicable to available in
the 32-bit SPI. The 16 bit Winsock2.DLL uses
WSPCallbackSelect() to implement the API function
WSAAsyncSelect().
This function is used to request that the service
provider should send a message to the window hWnd
whenever it detects any of the network events
specified by the lEvent parameter. The message
which should be sent is specified by the wMsg
parameter. The socket for which notification is
required is identified by s.
This function automatically sets socket s to non-
blocking mode, regardless of the value of lEvent.
See WSPIoctlSocketWSPioctlsocket() about how to
set the socket back to blocking mode.
The lEvent parameter is constructed by or'ing any
of the values specified in the following list.
Value Meaning
FD_READ Want to receive notification of
readiness for reading
FD_WRITE Want to receive notification of
readiness for writing
FD_OOB Want to receive notification of
the arrival of out-of-band data
FD_ACCEPT Want to receive notification of
incoming connections
FD_CONNECT Want to receive notification of
completed connection
FD_CLOSE Want to receive notification of
socket closure
FD_QOS Want to receive notification of
socket Quality of Service (QOS)
changes
FD_GROUP_QOS Want to receive notification
of socket group Quality of
Service (QOS) changes
Issuing a WSPAsyncSelect32() for a socket cancels
any previous WSPAsyncSelect32() for the same
socket. For example, to receive notification for
both reading and writing, the Winsock DLL will
application must call WSPAsyncSelect32() with both
FD_READ and FD_WRITE, as follows:
rc = WSPAsyncSelect32(s, hWnd, wMsg,
FD_READ|FD_WRITE, &error);
It is not possible to specify different messages
for different events. The following code will not
work; the second call will cancel the effects of
the first, and only FD_WRITE events will be
reported with message wMsg2:
rc = WSPAsyncSelect32WSAPsyncSelect(s, hWnd,
wMsg1, FD_READ, &error);
rc = WSPAsyncSelect32WSAPsyncSelect(s, hWnd,
wMsg2, FD_WRITE, &error);
To cancel all notification - i.e., to indicate
that the service provider Winsock2 should send no
further messages related to network events on the
socket - lEvent should be set to zero.
rc = WSPAsyncSelect32WSAPsyncSelect(s, hWnd, 0, 0,
&error);
Although in this instance WSPAsyncSelect32()
immediately disables event message posting for the
socket, it is possible that messages may be
waiting in the application's message queue. The
application must therefore be prepared to receive
network event messages even after cancellation.
Closing a socket with WSPCloseSocketclosesocket()
also cancels WSPAsyncSelect32() message sending,
but the same caveat about messages in the queue
prior to the WSPCloseSocketWSPclosesocket() still
applies.
Since a WSPAcceptWSPaccept()'ed socket has the
same properties as the listening socket used to
accept it, any WSPAsyncSelect32() events set for
the listening socket apply to the accepted socket.
For example, if a listening socket has
WSPAsyncSelect32() events FD_ACCEPT, FD_READ, and
FD_WRITE, then any socket accepted on that
listening socket will also have FD_ACCEPT,
FD_READ, and FD_WRITE events with the same wMsg
value used for messages. If a different wMsg or
events are desired, the application should call
WSPAsyncSelect32(), passing the accepted socket
and the desired new information.1
When one of the nominated network events occurs on
the specified socket s, the application's window
hWnd receives message wMsg. The wParam argument
identifies the socket on which a network event has
occurred. The low word of lParam specifies the
network event that has occurred. The high word of
lParam contains any error code. The error code be
any error as defined in Winsock2.h.
The error and event codes may be extracted from
the lParam using the macros WSAGETSELECTERROR and
WSAGETSELECTEVENT, defined in Winsock2.h as:
#define WSAGETSELECTERROR(lParam)
HIWORD(lParam)
#define WSAGETSELECTEVENT(lParam)
LOWORD(lParam)
The use of these macros will maximize the
portability of the source code for the
application.
The possible network event codes which may be
returned are as follows:
Value Meaning
FD_READ Socket s ready for reading
FD_WRITE Socket s ready for writing
FD_OOB Out-of-band data ready for
reading on socket s.
FD_ACCEPT Socket s ready for accepting a
new incoming connection
FD_CONNECT Connection initiated on socket s
completed
FD_CLOSE Connection identified by socket s
has been closed
FD_QOS Quality of Service associated
with socket s has changed.
FD_GROUP_QOS Quality of Service
associated with the socket group
to which s belongs has changed.
Return Value The return value is 0 if the application's
declaration of interest in the network event set
was successful. Otherwise the value SOCKET_ERROR
is returned, and a specific error code is
available in lpErrno.
Comments Although WSPAsyncSelect32() can be called with
interest in multiple events, the application
window will receive a single message for each
network event.
As in the case of the WSPSelectWSPselect()
function, WSPAsyncSelect32() will frequently be
used to determine when a data transfer operation
(WSPSendWSPsend() or WSPRecvWSPrecv()) can be
issued with the expectation of immediate success.
Nevertheless, a robust application must be
prepared for the possibility that it may receive a
message and issue a Winsock2 call which returns
WSAEWOULDBLOCK immediately. For example, the
following sequence of events is possible:
(i) data arrives on socket s; Winsock2 posts
WSPAsyncSelect32() message
(ii) application processes some other message
(iii) while processing, application issues an
WSPIoctlSocketWSPioctlsocket(s,
FIONREAD...) and notices that there is
data ready to be read
(iv) application issues a
WSPRecvWSPrecv(s,...) to read the data
(v) application loops to process next
message, eventually reaching the
WSPAsyncSelect32() message indicating
that data is ready to read
(vi) application issues
WSPRecvWSPrecv(s,...), which fails with
the error WSAEWOULDBLOCK.
Other sequences are possible.
The WinsockTheWinsock2 DLL will not continually
flood an application with messages for a
particular network event. Having successfully
posted notification of a particular event to an
application window, no further message(s) for that
network event will be posted to the application
window until the application makes the function
call which implicitly reenables notification of
that network event.
Event Re-enabling function
FD_READ WSPRecvWSPrecv() or
WSPRecvFromWSPrecvfrom()
FD_WRITE WSPSendWSPsend() or
WSPSendToWSPsendto() or
WSAGetBuffer()
FD_OOB WSPRecvWSPrecv()
FD_ACCEPT WSPAcceptWSPaccept() or
WSPAcceptEx() unless the error
code returned is WSATRY_AGAIN
indicating that the condition
function returned CF_DEFER
FD_CONNECT NONE
FD_CLOSE NONE
FD_QOS WSPGetSockOptWSPgetsockopt() with
option SO_FLOWSPEC
FD_GROUP_QOS WSPGetSockOptWSPgetsockopt() with
option SO_GROUP_FLOWSPEC
Any call to the reenabling routine, even one which
fails, results in reenabling of message posting
for the relevant event.
For FD_READ, FD_OOB, FD_ACCEPT, FD_QOS and
FD_GROUP_QOS events, message posting is "level-
triggered." This means that if the reenabling
routine is called and the relevant event is still
valid after the call, a WSPAsyncSelect32() message
is posted to the application. This allows an
application to be event-driven and not be
concerned with the amount of data that arrives at
any one time. Consider the following sequence:
(i) network transport stack receives 100
bytes of data on socket s and causes
Winsock2 to post an FD_READ message.
(ii) The application issues WSPRecvWSPrecv(
s, buffptr, 50, 0) to read 50 bytes.
(iii) another FD_READ message is posted since
there is still data to be read.
With these semantics, an application need not read
all available data in response to an FD_READ
message--a single WSPRecvWSPrecv() in response to
each FD_READ message is appropriate. If an
application issues multiple WSPRecvWSPrecv() calls
in response to a single FD_READ, it may receive
multiple FD_READ messages. Such an application may
wish to disable FD_READ messages before starting
the WSPRecvWSPrecv() calls by calling
WSPAsyncSelect32() with the FD_READ event not set.
If an event has already happened when the
application calls WSPAsyncSelect32() or when the
reenabling function is called, then a message is
posted as appropriate. All the events have
persistence beyond the occurrence of their
respective events. For example, consider the
following sequence: 1) an application calls
WSPListenWSPlisten(), 2) a connect request is
received but not yet accepted, 3) the application
calls WSPAsyncSelect32() specifying that it wants
to receive FD_ACCEPT messages for the socket. Due
to the persistence of events, Winsock2 posts an
FD_ACCEPT message immediately.
The FD_WRITE event is handled slightly
differently. An FD_WRITE message is posted when a
socket is first connected with
WSPConnectWSPconnect() or accepted with
WSPAcceptWSPaccept(), and then after a
WSPSendWSPsend() or WSPSendToWSPsendto(), or
WSAGetBuffer() fails with WSAEWOULDBLOCK and
buffer space becomes available. Therefore, an
application can assume that sends are possible
starting from the first FD_WRITE message and
lasting until a send returns WSAEWOULDBLOCK. After
such a failure the application will be notified
that sends are again possible with an FD_WRITE
message.
The FD_OOB event is used only when a socket is
configured to receive out-of-band data separately.
If the socket is configured to receive out-of-band
data in-line, the out-of-band (expedited) data is
treated as normal data and the application should
register an interest in, and will receive, FD_READ
events, not FD_OOB events. An application may set
or inspect the way in which out-of-band data is to
be handled by using WSPSetSockOptWSPsetsockopt()
or WSPGetSockOptWSPgetsockopt() for the
SO_OOBINLINE option.
The error code in an FD_CLOSE message indicates
whether the socket close was graceful or abortive.
If the error code is 0, then the close was
graceful; if the error code is WSAECONNRESET, then
the socket's virtual circuit was reset. This only
applies to connection-oriented sockets such as
SOCK_STREAM.
The FD_CLOSE message is posted when a close
indication is received for the virtual circuit
corresponding to the socket. In TCP terms, this
means that the FD_CLOSE is posted when the
connection goes into the FIN WAIT or CLOSE WAIT
states. This results from the remote end
performing a WSPShutdownWSPshutdown() on the send
side or a WSPCloseSocketWSPclosesocket().
Please note your application will receive ONLY an
FD_CLOSE message to indicate closure of a virtual
circuit, and only when all the received data has
been read if this is a graceful close. It will NOT
receive an FD_READ message to indicate this
condition.
The FD_QOS or FD_GROUP_QOS message is posted when
any field in the flow spec associated with socket
s or the socket group that s belongs to has
changed, respectively. Applications might use
WSPGetSockOptWSPgetsocketopt() with option
SO_FLOWSPEC or SO_GROUP_FLOWSPEC to get the
current QOS for socket s or for the socket group s
belongs to, respectively.
Error Codes WSAENETDOWN The network
subsystem has failed.
WSAEINVAL Indicates that one of the
specified parameters was
invalid, or the specified
socket is in an invalid state.
WSAEINPROGRESS A blocking Winsock2 call is in
progress, or the service
provider is still processing a
callback function (see section
???).
WSAENOTSOCK The descriptor is not a
socket.
Additional error codes may be set when an
application window receives a message. This error
code is extracted from the lParam in the reply
message using the WSAGETSELECTERROR macro.
Possible error codes for each network event are:
Event: FD_CONNECT
Error Code Meaning
WSAEADDRINUSE The specified address is
already in use.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAECONNREFUSED The attempt to connect was
forcefully rejected.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAETIMEDOUT Attempt to connect timed out
without establishing a
connection
Event: FD_CLOSE
Error Code Meaning
WSAENETDOWN The network subsystem has
failed.
WSAECONNRESET The connection was reset by
the remote side.
WSAECONNABORTED The connection was aborted due
to timeout or other failure.
Event: FD_READ
Event: FD_WRITE
Event: FD_OOB
Event: FD_ACCEPT
Event: FD_QOS
Event: FD_GROUP_QOS
Error Code Meaning
WSAENETDOWN The network subsystem has
failed.
See Also WSPSelectWSPselect()
3.1.2.13 WSPCallbackSelect16()
Description Request event notification for a socket via
the specified callback function.
#include <ws2spi.h>
int WSPAPI WSPCallbackSelect16 ( SOCKET s,
LPSELECTPROC lpfnCallback,
DWORD dwCallbackData, long lEvent, int FAR *
lpErrno );
s A descriptor identifying the socket for
which event notification is required.
lpfnCallback The procedure instance address of
the callback function to be invoked by
Winsock service providers whenever a
registered network event happens.
dwCallbackData The callback data which is passed
back to the application as a parameter
to the callback function. This object is
not interpreted by the Winsock service
provider.
lEvent A bitmask which specifies a combination
of network events in which the Winsock
DLL is interested.
lpErrno A pointer to the error code.
Remarks This function is only applicable toavailable in
the 16-bit SPI. The 16 bit Winsock2.DLL uses this
function to implement the select(),
WSAAsyncSelectWSAASyncSelect(), and
WSPEventSelectWSAEventSelect() API functions.
This function will enables the function-based
callback mechanism for the specified socket. The
callback function will be invoked whenever the
service provider detects any of the network events
specified by the lEvent parameter. The socket for
which notification is required is identified by s.
The value of dwCallbackData will be passed back to
the callerapplication as a parameter to the
callback function.
This function automatically sets socket s to non-
blocking mode.
The prototype of the callback function is as
follows:
VOID WSACALLBACK CallbackFunc( SOCKET s, long
lEvent, int ErrorCode, DWORD dwCallbackData );
CallbackFunc is a placeholder for athe Winsock DLL
supplied function pointername. The actual callback
function must reside in a DLL or application
module and be exported in the module definition
file. You must use MakeProcInstance() to get a
procedure-instance address for the callback
function. The callback function ismust be written
in such a way that it can be called by the
provider from within interrupt context2. (This
means that the only Winsock SPI calls that may be
made within the callback function are WSPSend(),
WSPsend(), WSPSendTo(), WSPsendto(), WSPRecv(),
WSPrecv(), and WSPRecvFrom() WSPrecvfrom()
provided that the socket option SO_INTERRUPT for
this socket s is TRUE and the MSG_INTERRUPT flag
for these functions is set.)
The lEvent parameter is constructed by or'ing any
of the values specified in the following list.
Value Meaning
FD_READ Want to receive notification of
readiness for reading
FD_WRITE Want to receive notification of
readiness for writing
FD_OOB Want to receive notification of
the arrival of out-of-band data
FD_ACCEPT Want to receive notification of
incoming connections
FD_CONNECT Want to receive notification of
completed connection
FD_CLOSE Want to receive notification of
socket closure
FD_QOS Want to receive notification of
Quality of Service (QOS) changes
FD_GROUP_QOS Want to receive notification
of socket group Quality of
Service (QOS) changes
FD_CLEANUP Want to receive notification
of completed clean-up operation
Issuing a WSPCallbackSelect16() for a socket
cancels any previous WSPCallbackSelect16() for the
same socket. For example, to receive notification
for both reading and writing, the Winsock DLL must
call WSPCallbackSelect16() with both FD_READ and
FD_WRITE, as follows:
rc = WSPCallbackSelect16(s, lpfnCallback,
dwCallbackData, FD_READ|FD_WRITE,
lpErrno);
It is not possible to specify different callback
data for different events. The following code will
not work; the second call will cancel the effects
of the first, and only FD_WRITE events will be
reported with dwCallbackData2:
rc = WSPCallbackSelect16(s, lpfnCallback,
dwCallbackData1, FD_READ, lpErrno);
rc = WSPCallbackSelect16(s, lpfnCallback,
dwCallbackData2, FD_WRITE, lpErrno);
To cancel all notification - i.e., to indicate
that the service provider should no long invoke
the callback function related to network events on
the socket - lEvent should be set to zero. In this
case, lpfnCallback and dwCallbackData are ignored.
rc = WSPCallbackSelect16(s, lpfnCallback,
dwCallbackData, 0, lpErrno);
Closing a socket with
WSPCloseSocketWSPclosesocket() also cancels
WSPCallbackSelect16() mechanism on the socket.
A WSPAccept()'ed socket has the same properties as
the listening socket used to accept it except that
no network events and callback function are
associated with it. Winsock2.DLL will subsequently
invoke WSPCallbackSelect16() to register interest
in the appropriate set of events for the
WSPAccept()'ed socket3.Since a PSAcceptEx()'ed
socket has the same properties as the listening
socket used to accept it, any PSCallbackSelect()
events set for the listening socket apply to the
accepted socket. For example, if a listening
socket has PSCallbackSelect() events FD_ACCEPT,
FD_READ, and FD_WRITE, then any socket accepted on
that listening socket will also have FD_ACCEPT,
FD_READ, and FD_WRITE events with the same
callback function. If a different callback
function or events are desired, PII.DLL should
call PSCallbackSelect(), passing the accepted
socket and the desired new information.
When one of the nominated network events occurs on
the specified socket s, the callback function will
be invoked. The s argument identifies the socket
on which a network event has occurred. The lEvent
argument specifies the network event that has
occurred. The ErrorCode argument contains any
error code. The error code can be any error as
defined in ws2spi.h.
The possible network event codes which may be
returned are as follows:
Value Meaning
FD_READ Socket s ready for reading
FD_WRITE Socket s ready for writing
FD_OOB Out-of-band data ready for
reading on socket s.
FD_ACCEPT Socket s ready for accepting a
new incoming connection
FD_CONNECT Connection initiated on socket s
completed
FD_CLOSE Connection identified by socket s
has been closed
FD_QOS Quality of Service associated
with socket s or the socket group
to which s belongs has been
changed.
FD_GROUP_QOS Quality of Service
associated with the socket group
to which s belongs has changed.
Return Value The return value is 0 if the Winsock's
declaration of interest in the network event set
was successful. Otherwise the value SOCKET_ERROR
is returned, and a specific error number is
available in lpErrno.
Comments Although WSPCallbackSelect16() can be called with
interest in multiple events, the Winsock DLL will
get a callback for each network event.
As in the case of WSPSelectWSPselect(),
WSPCallbackSelect16() isare frequently used to
determine when a data transfer operation
(WSPSendWSPPSsend() or WSPRecvWSPrecv()) can be
issued with the expectation of immediate success.
The Winsock service provider will not continually
flood the Winsock DLL with callbacks for a
particular network event on a given socket. Having
successfully invoked a callback indicating a
particular event to the Winsock DLL, no further
callback(s) for that network event on the socket
will be invoked to the Winsock DLL until the
Winsock DLL makes the function call which
implicitly reenables notification of that network
event, and returns from the callback function4.
Event Re-enabling function
FD_READ WSPRecvWSPrecv() or
WSPRecvFromWSPrecvfrom()
FD_WRITE WSPSendWSPsend() or
WSPSendToWSPsendto() or
WSAGetBuffer()
FD_OOB WSPRecvWSPrecv()
FD_ACCEPT WSPAccept() unless the error code
returned is WSATRY_AGAIN indicating
that the condition function
returned CF_DEFER
FD_CONNECT NONE
FD_CLOSE NONE
FD_QOS WSPGetSockOptWSPgetsockopt() with
option SO_FLOWSPEC
FD_GROUP_QOS WSPGetSockOptWSPgetsockopt() with
option SO_GROUP_FLOWSPEC
Any call to the reenabling routine, even one which
fails (except in the case of FD_ACCEPT when
WSPAccept() returns with error code WSATRY_AGAIN),
results in reenabling of callback invocation for
the relevant event.
For FD_READ, FD_OOB, FD_ACCEPT, FD_QOS and
FD_GROUP_QOS events, callback invocation is "level-
triggered." This means that if the reenabling
routine is called and the relevant event is still
valid after the call, an additional callback is
invoked after the previous callback returns. This
allows applications using Winsock2.DLL to be event-
driven and not be concerned with the amount of
data that arrives at any one time. Consider the
following sequence:
(i) The service provider receives 100 bytes
of data on socket s and invokes an
FD_READ callback.
(ii) The Winsock2.DLL issues WSPRecvWSPrecv(
s, buffptr, 50, 0, lpErrno) to read 50
bytes.
(iii) The service provider invokes another
FD_READ callback since there is still
data to be read.
With these semantics, the Winsock DLL need not
read all available data in response to an FD_READ
callback--a single WSPRecvWSPrecv() in response to
each FD_READ callback is appropriate. If the
Winsock DLL issues multiple WSPRecvWSPrecv() calls
in response to a single FD_READ, it may receive
multiple FD_READ callbacks.
If an event has already happened when the Winsock
DLL calls WSPCallbackSelect16()5 or when the
reenabling function is called, then a callback is
invoked as appropriate. All the events have
persistence beyond the occurrence of their
respective events. For example, if the Winsock DLL
calls WSPListenWSPlisten(), a connect attempt is
made, then the Winsock DLL calls
WSPCallbackSelect16() specifying that it wants to
receive FD_ACCEPT callbacks for the socket, the
service provider invokes an FD_ACCEPT callback
immediately.
The FD_WRITE event is handled slightly
differently. An FD_WRITE callback is invoked when
a socket is first connected with WSPConnect() or
accepted with WSPAccept, and then after a
WSPSendWSPsend() or WSPSendToWSPsendto(), or
WSAGetBuffer() fails with WSAEWOULDBLOCK and
buffer space becomes available. Therefore, the
Winsock DLL can assume that sends are possible
starting from the first FD_WRITE callback and
lasting until a send returns WSAEWOULDBLOCK. After
such a failure the Winsock DLL will be notified
that sends are again possible with an FD_WRITE
callback.
The FD_OOB event is used only when a socket is
configured to receive out-of-band data separately.
If the socket is configured to receive out-of-band
data in-line, the out-of-band (expedited) data is
treated as normal data and the Winsock DLL should
register an interest in, and will receive, FD_READ
events, not FD_OOB events. The Winsock DLL may set
or inspect the way in which out-of-band data is to
be handled by using WSPSetSockOptWSPsetsockopt()
or WSPGetSockOptWSPgetsockopt() for the
SO_OOBINLINE option.
The error code in an FD_CLOSE callback indicates
whether the socket close was graceful or abortive.
If the error code is 0, then the close was
graceful; if the error code is WSAECONNRESET, then
the socket's virtual circuit was reset. This only
applies to connection-oriented sockets such as
SOCK_STREAM.
The FD_CLOSE callback is invoked when a close
indication is received for the virtual circuit
corresponding to the socket. In TCP terms, this
means that the FD_CLOSE callback is invoked when
the connection goes into the FIN WAIT or CLOSE
WAIT states. This results from the remote end
performing a WSPShutdownWSPshutdown() on the send
side or a WSPCloseSocketWSPclosesocket().
Please note the Winsock DLL shouldwill receive
ONLY an FD_CLOSE callback to indicate closure of a
virtual circuit. It shouldwill NOT receive an
FD_READ callback to indicate this condition.
The FD_QOS or FD_GROUP_QOS callback is invoked
when any field in the flow spec associated with
socket s or the socket group to which s belongs
has changed, respectively. Winsock2.DLL should use
WSPGetSockOptWSPgetsockopt() with option
SO_FLOWSPEC or SO_GROUP_FLOWSPEC to get the
current QOS for socket s or for the socket group
to which s belongs, respectively.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this API.
WSAENETDOWN The network subsystem has
failed.
WSAEINVAL Indicates that one of the
specified parameters was
invalid, or the specified
socket is in an invalid state.
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEFAULT The lpfnCallback is not part
of the user address space.
WSAENOTSOCK The descriptor is not a
socket.
Additional error codes may be set when the Winsock
DLL receives a callback. Possible error codes for
each network event are:
Event: FD_CONNECT
Error Code Meaning
WSAEADDRINUSE The specified address is
already in use.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAECONNREFUSED The attempt to connect was
forcefully rejected.
WSAEDESTADDRREQ A destination address is
required.
WSAEFAULT The namelen argument is
incorrect.
WSAEINVAL The socket is already bound to
an address.
WSAEISCONN The socket is already
connected.
WSAEMFILE No more socket descriptors are
available.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAENOTCONN The socket is not connected.
WSAENOTSOCK The descriptor is not a
socket.
WSAETIMEDOUT Attempt to connect timed out
without establishing a
connection
Event: FD_CLOSE
Error Code Meaning
WSAENETDOWN The network subsystem has
failed.
WSAECONNRESET The connection was reset by
the remote side.
WSAECONNABORTED The connection was aborted due
to timeout or other failure.
Event: FD_READ
Event: FD_WRITE
Event: FD_OOB
Event: FD_ACCEPT
Event: FD_QOS
Event: FD_GROUP_QOS
Error Code Meaning
WSAENETDOWN The network subsystem has
failed.
Notes For
Winsock Service
Providers When a socket is closed, the Winsock service
provider should cancel any pending callbacks to
the Winsock DLL.
3.1.2.14 WSPCancelBlockingCall32()
Description Cancel a blocking call which is currently in
progress.
#include <ws2spi.h>
int WSPAPI WSPCancelBlockingCall32 ( int FAR *
lpErrno );
lpErrno A pointer to the error code.
Remarks This function is only applicable toavailable in
the 32-bit SPI.
This function cancels any outstanding blocking
operation for the current thread. It is normally
used in two situations:
1. An application is processing a message which has been
received while a blocking call is in progress. In this case,
WSPIsBlocking32() will be TRUE.
2. A blocking call is in progress, and Winsock has called
back to the applications "blocking hook" function (as
established by WSPSetBlockingHook32()).
In each case, the original blocking call will
terminate as soon as possible with the error
WSAEINTR. (In (1), the termination will not take
place until Windows message scheduling has caused
control to revert to the blocking routine in
Windows Sockets. In (2), the blocking call will be
terminated as soon as the blocking hook function
completes.)
In the case of a blocking WSPConnect() operation,
the Windows Sockets implementation will terminate
the blocking call as soon as possible, but it may
not be possible for the socket resources to be
released until the connection has completed (and
then been reset) or timed out. This is likely to
be noticeable only if the application immediately
tries to open a new socket (if no sockets are
available), or to WSPConnect() to the same peer.
Cancelling an WSPAccept() or a
WSPSelectWSPselect() call does not adversely
impact the sockets passed to these calls. Only the
particular call fails; any operation that was
legal before the cancel is legal after the cancel,
and the state of the socket is not affected in any
way.
Cancelling any operation other than WSPAaccept()
and WSPSelectWSPselect() can leave the socket in
an indeterminate state. If an application cancels
a blocking operation on a socket, the only
operation that the application can depend on being
able to perform on the socket is a call to
WSPCloseSocketWSPclosesocket(), although other
operations may work on some service provider
Windows Sockets implementations. If an application
desires maximum portability, it must be careful
not to depend on performing operations after a
cancel. An application may reset the connection by
setting the timeout on SO_LINGER to 0.
If a cancel operation compromised the integrity of
a SOCK_STREAM's data stream in any way, the
Windows Sockets implementation must reset the
connection and fail all future operations other
than WSPCloseSocketWSPclosesocket() with
WSAECONNABORTED.
Return Value The return value is 0 if the blocking
operation has been successfully cancelled.
Otherwise the value SOCKET_ERROR is returned, and
a specific error number is available in lpErrno.
On a blocking socket, the return value indicates
success or failure of the connection attempt.
Comments Note that it is possible that the network
operation completes before the
WSPCancelBlockingCall32() is processed, for
example if data is received into the user buffer
at interrupt time while the application is in a
blocking hook. In this case, the blocking
operation will return successfully as if
WSPCancelBlockingCall32() had never been called.
Note that the WSPCancelBlockingCall32() still
succeeds in this case; the only way to know with
certainty that an operation was actually canceled
is to check for a return code of WSAEINTR from the
blocking call.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The Windows Sockets
implementation has detected
that the network subsystem has
failed.
WSAEINVAL Indicates that there is no
outstanding blocking call.
WSAEINPROGRESS A blocking PII operation is in
progress.
See Also WSPIsBlocking32(), WSPSetBlockingHook32(),
WSPUnhookBlockingHook32()
PSCancelBlockingCall()
Description Cancel a blocking call which is currently in
progress.
#include <PII.h>
int PASCAL FAR PSCancelBlockingCall ( void );
Remarks This function cancels any outstanding blocking
operation for this task. It is normally used in
two situations:
(1) An application is processing a message which
has been received while a blocking call is in
progress. In this case, PSIsBlocking() will be
true.
(2) A blocking call is in progress, and PII has
called back to the application's "blocking hook"
function (as established by PSSetBlockingHook()).
In each case, the original blocking call will
terminate as soon as possible with the error
WSAEINTR. (In (1), the termination will not take
place until Windows message scheduling has caused
control to revert to the blocking routine in PII.
In (2), the blocking call will be terminated as
soon as the blocking hook function completes.)
In the case of a blocking PSconnect() operation,
the PII Service Provider will terminate the
blocking call as soon as possible, but it may not
be possible for the socket resources to be
released until the connection has completed (and
then been reset) or timed out. This is likely to
be noticeable only if the application immediately
tries to open a new socket (if no sockets are
available), or to PSconnect() to the same peer.
Canceling an PSaccept() or a PSselect() call does
not adversely impact the sockets passed to these
calls. Only the particular call fails; any
operation that was legal before the cancel is
legal after the cancel, and the state of the
socket is not affected in any way.
Canceling any operation other than PSaccept() and
PSselect() can leave the socket in an
indeterminate state. If an application cancels a
blocking operation on a socket, the only operation
that the application can depend on being able to
perform on the socket is a call to
PSclosesocket(), although other operations may
work on some PII Service Providers. If an
application desires maximum portability, it must
be careful not to depend on performing operations
after a cancel. An application may reset the
connection by setting the timeout on SO_LINGER to
0.
If a cancel operation compromised the integrity of
a SOCK_STREAM's data stream in any way, the PII
Service Provider must reset the connection and
fail all future operations other than
PSclosesocket() with WSAECONNABORTED.
Return Value The value returned by PSCancelBlockingCall()
is 0 if the operation was successfully canceled.
Otherwise the value SOCKET_ERROR is returned, and
a specific error number may be retrieved by
calling PSGetLastError().
Comments Note that it is possible that the network
operation completes before the
PSCancelBlockingCall() is processed, for example
if data is received into the user buffer at
interrupt time while the application is in a
blocking hook. In this case, the blocking
operation will return successfully as if
PSCancelBlockingCall() had never been called.
Note that the PSCancelBlockingCall() still
succeeds in this case; the only way to know with
certainty that an operation was actually canceled
is to check for a return code of WSAEINTR from the
blocking call.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The PII Service Provider has
detected that the network
subsystem has failed.
WSAEINVAL Indicates that there is no
outstanding blocking call.
3.1.2.15 WSPCleanup()
Description Terminate use of the Winsock service
provider.
#include <ws2spi.h>
int WSPAPI WSPCleanup ( LPCLEANUPPROC
lpfnCallback, DWORD dwCallbackData, int FAR *
lpErrno );
lpfnCallback The address of the callback
function to be invoked by the service
provider when the cleanup operation
completed.
dwCallbackData The callback data passed back to
the Winsock DLL along with the callback.
This object is not interpreted by the
Winsock service provider.
lpErrno A pointer to the error code.
Remarks The Winsock DLL is required to perform a
(successful) WSPStartup() call before it can use
Winsock service providers. When it has completed
the use of Winsock service providers, the Winsock
DLL must call WSPCleanup() to deregister itself
from a Winsock service provider and allow the
service provider to free any resources allocated
on behalf of the Winsock DLL. Any open connection-
oriented sockets that are connected when
WSPCleanup() is called are reset; sockets which
have been closed with
WSPCloseSocketWSPclosesocket() but which still
have pending data to be sent are not affected--the
pending data is still sent. When the cleanup
operation is finished, the specified callback
function will be invoked. The value of
dwCallbackData will be passed back to the Winsock
DLL along with the callback.
The prototype of the callback function is as
follows:
VOID WSACALLBACK CallbackFunc( int ErrorCode,
DWORD dwCallbackData );
CallbackFunc is a placeholder for athe Winsock DLL-
supplied function pointername. The callback
function is only called when the client thread
that invoked this SPI is blocked in an alertable
wait. The callback data is passed back to the
Winsock DLL along with the callback. This object
is not interpreted by the Winsock service
provider.
{I'm not convinced this is sufficient. Perhaps if
the first call to WSPCleanup() returns
WSAEWOULDBLOCK, then the Winsock DLL must wait for
the callback to be invoked before unloading the
provider DLL. Under Win32, the Winsock DLL would
need to be blocked in an alertable wait for the
callback (really a user-mode APC) to be invoked.
The callback routine (in the Winsock DLL) could
signal an event, waking the main thread. The main
thread could then unload the DLL. Just a
thought...}
There must be a call to PSCleanup() for every call
to PSStartup() made by a task. Only the final
PSCleanup() for that task does the actual cleanup;
the preceding calls simply decrement an internal
reference count in the PII service provider. A
naive application may ensure that PSCleanup() was
called enough times by calling PSCleanup() in a
loop until it returns WSANOTINITIALISED.
Return Value The return value is 0 if the operation has
been successfully initiated. Otherwise the value
SOCKET_ERROR is returned, and a specific error
number is available in lpErrno.
On a blocking socket, the return value indicates
success or failure of the connection attempt.
Comments Attempting to call PSCleanup() from within a
blocking hook and then failing to check the return
code is a common PII programming error. If an
application needs to quit while a blocking call is
outstanding, the application must first cancel the
blocking call with PSCancelBlockingCall() then
issue the PSCleanup() call once control has been
returned to the application.
Notes For
Winsock Service
Providers The Winsock DLL will make one and only one
WSPCleanup() call to indicate deregistration from
a Winsock service provider. This function can
thus, for example, be utilized to free up
allocated resources. {Yeah, but since each
protocol is represented as a separate service
provider, it's possible that the service
provider's DLL which implements multiple protocols
(e.g. TCP and UDP) could be called with
WSPCleanup() multiple times} {We have basically
two choices here. We could either a) make separate
WSPStartup() and WSPCleanup() calls for each
protocol/address_family/socket_type triple
supported by a given service provider DLL, or b)
provide a single WSPStartup() call when a service
provider is first loaded, and a single
WSPCleanup() when its time to close shop. I tend
to favorfavour b), as it places the burden of
responsibility on the Winsock DLL, where it's
easier to control & get right (once).}
A PII service provider must be prepared to deal
with an application which terminates without
invoking PSCleanup() - for example, as a result of
an error.
In a multithreaded environment, WSPCleanup()
terminates Winsock operations for all threads.
A Winsock service provider must ensure that
WSPCleanup() leaves things in a state in which the
Winsock DLL can invoke WSPStartup() to re-
establish Winsock usage.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT The lpfnCallback is not part
of the user address space.
WSAEINPROGRESS A blocking PII operation is in
progress.
See Also WSPStartup()
3.1.2.16 WSPConnect()
Description Establish a connection to a peer, create
and/or join a socket group, and specify needed
quality of service based on the supplied flow
spec.
#include <ws2spi.h>
int WSPAPI WSPConnect ( SOCKET s, const struct
sockaddr FAR * name, int namelen, LPWSABUF
lpCallerData, LPWSABUF lpCalleeData, GROUP g,
LPQOS lpSFlowspec, int iSFlowspecLen, LPQOS
lpGFlowspec, int iGFlowspecLen, int FAR * lpErrno
);
s A descriptor identifying an unconnected
socket.
name The name of the peer to which the socket
is to be connected.
namelen The length of the name.
lpCallerData A pointer to the user data that is
to be transferred to the peer during
connection establishment.
lpCalleeData A pointer to the user data that is
to be transferred back from the peer
during connection establishment.
g The identifier of the socket group.
lpSFlowspec A pointer to the flow specs for
socket s, one for each direction, if s
is a DSTREAM type socket. Otherwise,
this parameter is ignored.
iSFlowspecLen The length of the flow spec for
socket s, if s is unidirectional and
DSTREAM type socket. Otherwise, this
parameter is ignored.
lpGFlowspec A pointer to the flow specs for the
socket group to be created, one for each
direction, if the value of parameter g
is SG_CONSTRAINED_GROUP. Otherwise, this
parameter is ignored.
lpErrno A pointer to the error code.
iGFlowspecLen The length of the flow spec for the
socket group to be created, if the value
of parameter g is SG_CONSTRAINED_GROUP.
Otherwise, this parameter is ignored.
Remarks This function is used to create a connection to
the specified destination, and to perform a number
of other ancillary operations that occur at
connect time as well. For connection-oriented
sockets (e.g., type SOCK_STREAM), an active
connection is initiated to the foreign host using
name (an address in the name space of the socket;
for a detailed description, please see
WSPBindWSPbind()). When this call completes
successfully, the socket is ready to send/receive
data.
For a connectionless socket (e.g., type
SOCK_UNREL_DGRAM), the operation performed by
WSPConnect() is merely to establish a default
destination address which will be used on
subsequent WSPSendWSPsend() and WSPRecvWSPrecv()
calls. Exchange of user to user data and QOS
specification are not possible and the
corresponding parameters will be ignored.
If the socket, s, is unbound, unique values are
assigned to the local association by the system,
and the socket is marked as bound. Note that if
the address field of the name structure is all
zeroes, WSPConnect() will return the error
WSAEADDRNOTAVAIL.
The Winsock DLL is responsible for allocating any
memory space pointed to directly or indirectly by
any of the parameters it specified. LPWSABUF and
LPQOS are defined in ws2spi.h as follows:
typedef struct _WSABUF {
int len; // the length of the
buffer
char FAR * buf; // the pointer to
the buffer
} WSABUF, FAR * LPWSABUF;
typedef enum
{
GuaranteedService,
BestEffortService
} GUARANTEE;
typedef struct _flowparams
{
int64 AverageBandwidth;// In
Bytes/sec
int64 PeakBandwidth; // In
Bytes/sec
int64 BurstLength; // In
microseconds
int64 Latency; // In
microseconds
int64 DelayVariation; // In
microseconds
GUARANTEE levelOfGuarantee;// Guaranteed
or
// Best Effort
int32 CostOfCall; //
Reserved for future
// use, must be set
to 0
int32 ProviderId; //
Provider Identifier
int32 SizePSP; // Length of
provider
// specific
parameters
UCHAR
ProviderSpecificParams[1];// provider specific
// parameters
} FLOWPARAMS;
typedef struct _QualityOfService
{
FLOWPARAMS ForwardFP; //
Caller(Initiator) to callee
FLOWPARAMS BackwardFP; // Callee
to caller
} QOS, FAR * LPQOS;
The lpCallerData is a value parameter which
contains any user data that is to be sent along
with the connection request. If lpCallerData is
NULL, no user data will be passed to the peer. The
lpCalleeData is a result parameter which will
contain any user data passed back from the peer as
part of the connection establishment. If
lpCalleeData->len is 0, no user data has been
passed back. The lpCalleeData information will be
valid when the connection operation is complete,
i.e., after the FD_CONNECT notification has
occurred. If lpCalleeData is NULL, no user data
will be passed back. The exact format of the user
data is specific to the address family to which
the socket belongs.
Parameter g is used to indicate the appropriate
actions on socket groups:
if g is an existing socket group id, add s to
this group, provided all the
requirements set by this group are met; or
if g = SG_UNCONSTRAINED_GROUP, create an
unconstrained socket group and have
s as the first member; or
if g = SG_CONSTRAINED_GROUP, create a
constrained socket group and have s as
the first member; or
if g = NULL, no operation is performed, and
is equivalent to connect().
For unconstrained group, any set of sockets may be
grouped together as long as they are supported by
a single Winsock service provider and are
connection-oriented. A constrained socket group
requires that connections on all grouped sockets
be to the same host. For newly created socket
groups, the new group id can be retrieved by using
WSPGetSockOptWSPgetsockopt() with option
SO_GROUP_ID, if this operation completes
successfully.
lpSFlowspec, and iSFlowspecLen specifies two
blocks of memory containing the flow specs for
socket s, one for each direction, if s is a
DSTREAM type socket. Otherwise, these values are
ignored. The forward QOS or backward QOS values
will be ignored as appropriate for unidirectional
sockets. for UNI_RECV type socket. The backward
QOS value will be ignored for UNI_SEND type
socket. The first part of each memory block is
struct FLOWSPEC, optionally followed by any
service provider specific portion. Thus,
lpSFlowspec->Flen and lpSFlowspec->Blen must be
larger than or equal to the size of struct
FLOWSPEC. A NULL value for lpSFlowspec indicates
no application supplied flow spec.
lpGFlowspec, and iGFlowspecLen specifies two
blocks of memory containing the flow specs for the
socket group to be created, one for each
direction, provided that the value of parameter g
is SG_CONSTRAINED_GROUP. Otherwise, these values
are ignored. The first part of each memory block
is struct FLOWSPEC, optionally followed by any
service provider specific portion. Thus,
lpGFlowspec->Flen and lpGFlowspec->Blen must be
larger than or equal to the size of struct
FLOWSPEC. A NULL value for lpGFlowspec indicates
no application supplied flow spec.
Comments When connected sockets break (i.e. become closed
for whatever reason), they should be discarded and
recreated. It is safest to assume that when things
go awry for any reason on a connected socket, the
Winsock DLL must discard and recreate the needed
sockets in order to return to a stable point.
Return Value If no error occurs, WSPConnect() returns 0.
Otherwise, it returns SOCKET_ERROR, and a specific
error code is available in lpErrno.
On a blocking socket, the return value indicates
success or failure of the connection attempt.
Error Codes The following errors may occur at the time of
the function call, and indicate that the connect
operation could not be initiated.
WSANOTINITIALISED A successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEADDRINUSE The specified address is
already in use.
WSAEINTR The (blocking) call was
canceled via
PSCancelBlockingCall().
WSAEINPROGRESS The function is invoked when a
callback is in progress.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAEDESTADDREQ A destination address is
required.
WSAEFAULT The namelen argument is
incorrect, the buffer length
for lpCalleeData, lpSFlowspec,
and lpGFlowspec are too small,
or the buffer length for
lpCallerData is too large.
WSAEINVAL The parameter g specified in
the condition function is not
a valid value, or the
parameter s is a listening
socket.
WSAEISCONN The socket is already
connected.
WSAEMFILE No more socket descriptors are
available.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAENOTSOCK The descriptor is not a
socket.
WSAEPROTONOSUPPORT The lpCallerData augment is
not supported by the service
provider.
WSAEWOULDBLOCK The socket is marked as non-
blocking and the connection
cannot be completed
immediately. It is possible
to PSselect() the socket while
it is connecting by
PSselect()ing it for writing.
The following error codes may be returned by
WSPEnumNetworkEvents() after the connect has
completed.
WSANOTINITIALISED A successful PSStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEADDRINUSE The specified address is
already in use.
WSAEINTR The (blocking) call was
canceled via
PSCancelBlockingCall().
WSAEINPROGRESS A blocking PII call is in
progress.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAECONNREFUSED The attempt to connect was
forcefully rejected.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAEOPNOTSUPP The flow specs specified in
lpSFlowspec and lpGFlowspec
cannot be satisfied.
WSAETIMEDOUT Attempt to connect timed out
without establishing a
connection
See Also WSPAccept(), WSPBindWSPbind(),
WSPGetSockNameWSPgetsockname(),
WSPGetSockOptWSPgetsockopt(), WSPsocket(),
WSPSelectWSPselect(), WSPEventSelect(),
WSPEnumNetworkEvents().
3.1.2.17 WSPEnumNetworkEvents()
Description Discover occurrences of network events for
the indicated socket.
#include <ws2spi.h>
int WSPAPI WSPEnumNetworkEvents ( SOCKET s,
WSAEVENT hEventObject, LPWSANETWORKEVENT
lpNetworkEvents, LPINT lpiCount, int FAR * lpErrno
);
s A descriptor identifying the socket.
hEventObject An optional handle identifying an
associated event object to be reset.
lpNetworkEvents An array of WSANETWORKEVENT
structs, each of which records an
occurred network event and the
associated error code.
lpiCount The number of elements in the array.
Upon returning, this parameter indicates
the actual number of elements in the
array, or the minimum number of elememts
needed to retrieve all the network
events if the return value is
WSAENOBUFS.
lpErrno A pointer to the error code.
Remarks This function is used to discover which network
events have occurred for the indicated socket
since the last invocation of this function. It is
intended for use in conjunction with
WSPEventSelect(), which associates an event object
with one or more network events. The socket's
internal record of network events is copied to
lpNetworkEvents, whereafter the internal network
events record is cleared. If hEventObject is non-
null, the indicated event object is also reset.
The Winsock2 DLL guarantees that the operations of
copying the network event record, clearing it and
resetting any associated event object are atomic,
such that the next occurrence of a nominated
network event will cause the event object to
become set.
The following error codes may be returned along
with the respective network event:
Event: FD_CONNECT
Error Code Meaning
WSAEADDRINUSE The specified address is
already in use.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAECONNREFUSED The attempt to connect was
forcefully rejected.
WSAENETUNREACH The network can't be reached
from this host at this time.
WSAENOBUFS No buffer space is available.
The socket cannot be
connected.
WSAETIMEDOUT Attempt to connect timed out
without establishing a
connection
Event: FD_CLOSE
Error Code Meaning
WSAENETDOWN The network subsystem has
failed.
WSAECONNRESET The connection was reset by
the remote side.
WSAECONNABORTED The connection was aborted due
to timeout or other failure.
Event: FD_READ
Event: FD_WRITE
Event: FD_OOB
Event: FD_ACCEPT
Event: FD_QOS
Event: FD_GROUP_QOS
Error Code Meaning
WSAENETDOWN The network subsystem has
failed.
Return Value The return value is 0 if the operation was
successful. Otherwise the value SOCKET_ERROR is
returned, and a specific error number is available
in lpErrno.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEINVAL Indicates that one of the
specified parameters was
invalid
WSAEINPROGRESS A blocking Winsock call is in
progress, or the service
provider is still processing a
callback function (see section
???).
WSAENOBUFS The supplied buffer is too
small.
See Also WSPEventSelect()
3.1.2.18 WSPEventSelect()
Description Specify an event object to be associated with
the supplied set of FD_XXX network events.
#include <ws2spi.h>
int WSPAPI WSPEventSelect ( SOCKET s, WSAEVENT
hEventObject, long lNetworkEvents, int FAR *
lpErrno );
s A descriptor identifying the socket.
hEventObject A handle identifying the event
object to be associated with the
supplied set of FD_XXX network events.
lNetworkEvents A bitmask which specifies the
combination of FD_XXX network events in
which the application has interest.
lpErrno A pointer to the error code.
Remarks This function is used to specify an event object,
hEventObject, to be associated with the selected
FD_XXX network events, lNetworkEvents. The socket
for which an event object is specified is
identified by s. The event object is set when any
of the nominated network events occuroccurr.
WSPEventSelect() operates very similarly to
WSPAsyncSelect32(), the difference being in the
actions taken when a nominated network event
occurs. Whereas WSPAsyncSelect32() causes an
application-specified Windows message to be
posted, WSPEventSelect() sets the associated event
object and records the occurrence of this event by
setting the corresponding bit in an internal
network event record. An application can use
WSAWaitForMultipleEvents() or
WSAGetOverlappedResult() to wait or poll on the
event object, and use WSAEnumNetworkEvents() to
retrieve the contents of the internal network
event record and thus determine which of the
nominated network events have occurred.
This function automatically sets socket s to non-
blocking mode, regardless of the value of
lNetworkEvents. See WSPIoctlSocketWSPioctlsocket()
about how to set the socket back to blocking mode.
FD_ACCEPT Want to receive notification of
incoming connections
FD_CONNECT Want to receive notification
of completed connection
FD_CLOSE Want to receive notification of
socket closure
The lNetworkEvents parameter is constructed by
or'ing any of the values specified in the
following list.
Value Meaning
FD_READ Want to receive notification of
readiness for reading
FD_WRITE Want to receive notification of
readiness for writing
FD_OOB Want to receive notification of
the arrival of out-of-band data
FD_ACCEPT Want to receive notification of
incoming connections
FD_CONNECT Want to receive notification of
completed connection
FD_CLOSE Want to receive notification of
socket closure
FD_QOS Want to receive notification of
socket Quality of Service (QOS)
changes
FD_GROUP_QOS Want to receive notification
of socket group Quality of
Service (QOS) changes
Issuing a WSPEventSelect() for a socket cancels
any previous WSPAsyncSelect32() or
WSPEventSelect() for the same socket and clears
all bits in the internal network event record. For
example, to associate an event object with both
reading and writing network events, the
application must call WSPEventSelect() with both
FD_READ and FD_WRITE, as follows:
rc = WSPEventSelect(s, hEventObject,
FD_READ|FD_WRITE);
It is not possible to specify different event
objects for different network events. The
following code will not work; the second call will
cancel the effects of the first, and only FD_WRITE
network event will be associated with
hEventObject2:
rc = WSPEventSelect(s, hEventObject1, FD_READ);
rc = WSPEventSelect(s, hEventObject2, FD_WRITE);
To cancel the association and selection of network
events on a socket, lNetworkEvents should be set
to zero, in which case the hEventObject parameter
will be ignored.
rc = WSPEventSelect(s, hEventObject, 0);
Closing a socket with
WSPCloseSocketWSPclosesocket() also cancels the
association and selection of network events
specified in WSPEventSelect() for the socket. The
application, however, still needs to call
WSACloseEvent() to explicitly close the event
object and free any resources.
Since a WSAAccept()'ed socket has the same
properties as the listening socket used to accept
it, any WSPEventSelect() association and network
events selection set for the listening socket
apply to the accepted socket. For example, if a
listening socket has WSPEventSelect() association
of hEventOject with FD_ACCEPT, FD_READ, and
FD_WRITE, then any socket accepted on that
listening socket will also have FD_ACCEPT,
FD_READ, and FD_WRITE network events associated
with the same hEventObject. If a different
hEventObject or network events are desired, the
application should call WSPEventSelect(), passing
the accepted socket and the desired new
information.6
Return Value The return value is 0 if the application's
specification of the network events and the
associated event object was successful. Otherwise
the value SOCKET_ERROR is returned, and a specific
error number is available in lpErrno.
Comments The scenarios that an event object is signaled is
dependent on the associated network events. The
scenarios for each network event are listed below:
Event Scenarios the associated event
object get signaled
FD_READ When data arrives in an emply
transport internal queue, or at the
end of the recv()/recvfrom() call
if there is more data to be read.
FD_WRITE When a socket is first connected
with connect() or accepted with
accept(), or after a send() or
sendto(), or WSAGetBuffer() fails
with WSAEWOULDBLOCK and buffer
space becomes available or
WSAGetBuffer()
FD_OOB The same as FD_READ, but with out-
of-band data.
FD_ACCEPT When an incoming connection request
arrives, or at the end of accept()
or WSAAcceptEx() (unless the error
code returned is WSATRY_AGAIN) if
there are more incoming connection
requests.
FD_CONNECT When the connect operation
completed.
FD_CLOSE When the remote side closes the
virtual circuit and the application
has read all bufferred data for the
socket.
FD_QOS When the socket QOS changes.
FD_GROUP_QOS When the group QOS changes.
If an network event has already happened when the
application calls WSAEventSelect(), then the
associated event object get signaled as
appropriate.
As in the case of the WSPSelectWSPselect() and
WSPAsyncSelect32() functions, WSPEventSelect()
will frequently be used to determine when a data
transfer operation (WSPSendWSPsend() or
WSPRecvWSPrecv()) can be issued with the
expectation of immediate success. Nevertheless, a
robust application must be prepared for the
possibility that the event object is set and it
issues a Winsock call which returns WSAEWOULDBLOCK
immediately. For example, the following sequence
of operations is possible:
(i) data arrives on socket s; Winsock sets
the WSPEventSelect event object
(ii) application does some other processing
(iii) while processing, application issues an
WSPIoctlSocketWSPioctlsocket(s,
FIONREAD...) and notices that there is
data ready to be read
(iv) application issues a
WSPRecvWSPrecv(s,...) to read the data
(v) application eventually waits on event
object specified in WSPEventSelect,
which returns immediately indicating
that data is ready to read
(vi) application issues
WSPRecvWSPrecv(s,...), which fails with
the error WSAEWOULDBLOCK.
Other sequences are possible.
Having successfully recorded the occurrence of the
network event (by setting the corresponding bit in
the internal network event record) and signaled
the associated event object, no further actions
are taken for that network event until the
application makes the function call which
implicitly reenables the setting of that network
event and signaling of the associated event
object.
Network Event Re-enabling function
FD_READ WSPRecvWSPrecv() or
WSPRecvFromWSPrecvfrom()
FD_WRITE WSPSendWSPsend() or
WSPSendToWSPsendto() or
WSAGetBuffer()
FD_OOB WSPRecvWSPrecv()
FD_ACCEPT WSPAccept() unless the error code
returned is WSATRY_AGAIN indicating
that the condition function
returned CF_DEFER
FD_CONNECT NONE
FD_CLOSE NONE
FD_QOS WSPGetSockOptWSPgetsockopt() with
option SO_FLOWSPEC
FD_GROUP_QOS WSPGetSockOptWSPgetsockopt() with
option SO_GROUP_FLOWSPEC
Any call to the reenabling routine, even one which
fails, results in reenabling of recording and
setting for the relevant network event and event
object, respectively.
For FD_READ, FD_OOB, FD_ACCEPT, FD_QOS and
FD_GROUP_QOS network events, network event
recording and event object setting are "level-
triggered." This means that if the reenabling
routine is called and the relevant network
condition is still valid after the call, the
network event is recorded and the associated event
object is set . This allows an application to be
event-driven and not be concerned with the amount
of data that arrives at any one time. Consider the
following sequence:
(i) transport provider receives 100 bytes of
data on socket s and causes Winsock2 DLL
to record the FD_READ network event and
set the associated event object.
(ii) The application issues WSPRecvWSPrecv(
s, buffptr, 50, 0) to read 50 bytes.
(iii) The transport provider causes WINSOCK
DLL to record the FD_READ network event
and sets the associated event object
again since there is still data to be
read.
With these semantics, an application need not read
all available data in response to an FD_READ
network event --a single WSPRecvWSPrecv() in
response to each FD_READ network event is
appropriate. If an application issues multiple
recv() calls in response to a single FD_READ, it
may receive multiple FD_READ messages. Such an
application may wish to disable FD_READ messages
before starting the recv() calls by calling
WSAAsyncSelect() with the FD_READ event not set.
If a network event has already happened when the
application calls WSPEventSelect() or when the
reenabling function is called, then a network
event is recorded and the associated event object
is set as appropriate. All the network events have
persistence beyond the occurrence of their
respective events. For example, consider the
following sequence: 1) an application calls
WSPListenWSPlisten(), 2) a connect request is
received but not yet accepted, 3) the application
calls WSPEventSelect() specifying that it is
interested in the FD_ACCEPT network event for the
socket. Due to the persistence of network events,
Winsock records the FD_ACCEPT network event and
sets the associated event object immediately.
The FD_WRITE network event is handled slightly
differently. An FD_WRITE network event is recorded
when a socket is first connected with WSPConnect()
or accepted with WSPAccept(), and then after a
WSPSendWSPsend() or WSPSendToWSPsendto(), or
WSAGetBuffer() fails with WSAEWOULDBLOCK and
buffer space becomes available. Therefore, an
application can assume that sends are possible
starting from the first FD_WRITE network event
settingsettting and lasting until a send returns
WSAEWOULDBLOCK. After such a failure the
application will find out that sends are again
possible when an FD_WRITE network event is
recorded and the associated event object is set .
The FD_OOB network event is used only when a
socket is configured to receive out-of-band data
separately. If the socket is configured to receive
out-of-band data in-line, the out-of-band
(expedited) data is treated as normal data and the
application should register an interest in, and
will get, FD_READ network event, not FD_OOB
network event. An application may set or inspect
the way in which out-of-band data is to be handled
by using WSPSetSockOptWSPsetsockopt() or
WSPGetSockOptWSPgetsockopt() for the SO_OOBINLINE
option.
The error code in an FD_CLOSE network event
indicates whether the socket close was graceful or
abortive. If the error code is 0, then the close
was graceful; if the error code is WSAECONNRESET,
then the socket's virtual circuit was reset. This
only applies to connection-oriented sockets such
as SOCK_STREAM.
The FD_CLOSE network event is recorded when a
close indication is received for the virtual
circuit corresponding to the socket. In TCP terms,
this means that the FD_CLOSE is recorded when the
connection goes into the FIN WAIT or CLOSE WAIT
states. This results from the remote end
performing a WSPShutdownWSPshutdown() on the send
side or a WSPCloseSocketWSPclosesocket().
Please note Winsock will record ONLY an FD_CLOSE
network event to indicate closure of a virtual
circuit. It will NOT record an FD_READ network
event to indicate this condition.
The FD_QOS or FD_GROUP_QOS network event is
recorded when any field in the flow spec
associated with socket s or the socket group that
s belongs to has changed, respectively.
Applications should use
WSPGetSockOptWSPgetsocketopt() with option
SO_FLOWSPEC or SO_GROUP_FLOWSPEC to get the
current QOS for socket s or for the socket group s
belongs to, respectively.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEINVAL Indicates that one of the
specified parameters was
invalid, or the specified
socket is in an invalid state.
WSAEINPROGRESS A blocking Winsock call is in
progress, or the service
provider is still processing a
callback function (see section
???).
WSAENOTSOCK The descriptor is not a
socket.
See Also WSPEnumNetworkEvents()
3.1.2.19 WSPIsBlocking32()
Description Determine if a blocking call is in progress.
#include <ws2spi.h>
BOOL WSPAPI WSPIsBlocking32 ( VOID );
Remarks This function is only applicable to the 32-bit
SPIis only available in the 32-bit SPI.
This function allows the Winsock DLL to determine
if it is executing while waiting for a previous
blocking call to complete.
Return Value The return value is TRUE if there is an
outstanding blocking function awaiting completion.
Otherwise, it is FALSE.
On a blocking socket, the return value indicates
success or failure of the connection attempt.
See Also WSPCancelBlockingCall32(), WSPSetBlockingHook32(),
WSPUnhookBlockingHook32()
3.1.2.210 WSPRrecv()
Description Receive data from a socket. {warning! Since
both the recv() and WSARecv() API functions map to
this function the description needs to be more
generic with respect to overlapped I/O This also
applies to WSPRecvFromWSPrecvFrom, WSPSendWSPSend,
WSPSendToWSPSendTo}
#include <ws2spi.h>
int WSPAPI WSPRecvWSPrecv ( SOCKET s, LPVOID
lpBuffer, DWORD nNumberOfBytesToRecv, LPDWORD
lpNumberOfBytesRecvd, LPINT lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine, int FAR * lpErrno );
s A descriptor identifying an
overlapped, connected socket. which
was created using WSPSocket() with
flag WSA_FLAG_OVERLAPPED.
lpBuffer A pointer to the buffer for the
incoming data.
nNumberOfBytesToRecv The number of bytes to
receive from the network.
lpNumberOfBytesRecvd A pointer to the number
of bytes received by this call.
lpFlags A pointer to flags.
lpOverlapped A pointer to a WSAOVERLAPPED
structure.
lpCompletionRoutine A pointer to the completion
routine called when the receive
operation has been completed.
lpErrno A pointer to the error code.
Remarks This function is used on a connection-oriented
socket specified by s to post a buffer into which
incoming data will be placed as it becomes
available. It can also be used on connectionless
sockets which have a stipulated default peer
address established via the WSPConnect()
functions.
For non-overlapped socket, this function behaves
like the standard recv() API with identical
blocking semantics and the lpOverlapped and
lpCompletionRoutine parameters are ignored. The
completion status of this SPI is the final
completion status of the receive operation.
For overlapped sockets, the final completion
status is retrieved via the
WSAGetOverlappedResult() API.
For byte stream style sockets (e.g., type
SOCK_STREAM), incoming data is placed into the
buffer until the buffer is filled. If the socket
has been configured for in-line reception of out-
of-band data (socket option SO_OOBINLINE) and out-
of-band data is unread, only out-of-band data will
be filled. The application may use the
ioctlsocket() SIOCATMARK to determine whether any
more out-of-band data remains to be read.
For message-oriented sockets (e.g., type
SOCK_DGRAM), an incoming message is placed into
the supplied buffer, up to the size of the buffer
supplied. If the message is larger than the buffer
supplied, the buffer is filled with the first part
of the message, the excess data is lost, and
WSPRecvWSPrecv() indicatesreturns the error
WSAEMSGSIZE.
If no incoming data is available at the socket,
the recv() call waits for data to arrive unless
the socket is non-blocking. In this case a value
of SOCKET_ERROR is returned with the error code
set to WSAEWOULDBLOCK. The select(),
WSAAsyncSelect() or WSACallbackSelect() calls may
be used to determine when more data arrives.
If the socket is connection-oriented and the
remote side has shut down the connection
gracefully, WSPRecvWSPrecv() will complete
immediately indicating zero bytes received. If the
connection has been reset, a WSPRecvWSPrecv() will
fail with the error WSAECONNRESET.
This function may be called from within the
completion routine of a previous WSPRecvWSPrecv(),
WSPRecvFromWSPrecvfrom(), WSPSendWSPsend() or
WSPSendToWSPsendto() function.
When called with an overlapped socket, the
lpOverlapped parameter much be valid for the
duration of the overlapped operation. The
WSAOVERLAPPED structure has the following form:
typedef struct _WSAOVERLAPPED {
DWORD Internal; //
reserved
DWORD InternalHigh; //
reserved
DWORD Offset; // ignored
DWORD OffsetHigh; //
ignored
WSAEVENT hEvent;
} WSAOVERLAPPED, LPWSAOVERLAPPED;
If the lpCompletionRoutine parameter is NULL, the
hEvent field of lpOverlapped must be an event
object handle which is signaled when the
overlapped operation completes. An application can
use WSAWaitForMultipleEvents() or
WSAGetOverlappedResult() to wait or poll on the
event object.
The lpCompletionRoutine must be non-NULL and the
hEvent field is used to pass context information
to the completion routine.
The prototype of the completion routine is as
follows:
VOID CALLBACK CompletionRoutine( SOCKET s,
DWORD dwError, DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped );
CompletionRoutine is a placeholder for an
application-defined or library-defined function
pointername. dwError specifies the completion
status for the overlapped operation as indicated
by lpOverlapped. cbTransferred specifies the
number of bytes received. This function does not
return a value.
Returning from this function allows invocation of
another pending completion routine for this
socket. In Win32 environments, all waiting
completion routines are called before the
alterable thread's wait is satisfied with a return
code of WSA_IO_COMPLETION. The completion routines
may be called in any order, not necessarily in the
same order the overlapped operations are
completed. However, the posted buffers are
guaranteed to be filled in the same order they are
supplied
lpFlags may be used to influence the behavior of
the function invocation beyond the options
specified for the associated socket. That is, the
semantics of this function are determined by the
socket options and the lpFlags parameter. The
latter is constructed by or-ing any of the
following values:
Value Meaning
MSG_PEEK Peek at the incoming data. The data is
copied into the buffer but is not
removed from the input queue. {Hmmm,
"input queue" implies receive buffering
is occurring, which sort of defeats the
purpose of overlapped I/O. Should this
be a valid flag for overlapped I/O?}
MSG_OOB Process out-of-band data (See section
for a discussion of this topic.)
Upon the completion of the overlapped operation,
the lpNumberOfBytesRecvd parameter is filled with
the number of bytes received, and, for message-
oriented sockets, the MSG_PARTIAL bit is set in
the lpFlags parameter if a partial message is
received. If a complete message is received,
MSG_PARTIAL is cleared in lpFlags.
Return Value If no error occurs, WSPRecvWSPrecv() returns
the number of bytes received. If the connection
has been closed, it returns 0. Otherwise, a value
of SOCKET_ERROR is returned, and a specific error
code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAENOTCONN The socket is not connected.
WSAEINTR The (blocking) call was
canceled via
WSACancelBlockingCall().
WSAEINPROGRESS A blocking PII operation is in
progress.
WSAENETRESET The connection must be reset
because the service provider
dropped it.
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP MSG_OOB was specified, but the
socket is not stream style
such as type SOCK_STREAM, out-
of-band data is not supported
in the communication domain
associated with this socket,
or the socket is
unidirectional and supports
only send operations.
WSAESHUTDOWN The socket has been shutdown;
it is not possible to
WSPRecvWSPrecv() on a socket
after WSPShutdownWSPshutdown()
has been invoked with how set
to SD_RECEIVE or SD_BOTH.
WSAEWOULDBLOCK There are too many outstanding
overlapped I/O requests.
WSAEMSGSIZE The message was too large to
fit into the specified buffer
and was truncated. Any
trailing portion of the
message that did not fit into
the buffer has been discarded.
{Does this make sense?}
WSAEINVAL The socket has not been bound
with WSPBindWSPbind(), or the
socket is not created with the
overlapped flag.
WSAECONNABORTED The virtual circuit was
aborted due to timeout or
other failure.
WSAECONNRESET The virtual circuit was reset
by the remote side.
See Also WSPSocket()
3.1.2.121 WSPRecvFromWSPrecvfrom()
Description Receive a datagram and store the source
address.
#include <ws2spi.h>
int WSPAPI WSPRecvFromWSPrecvfrom ( SOCKET s,
LPVOID lpBuffer, DWORD nNumberOfBytesToRecv,
LPDWORD lpNumberOfBytesRecvd, LPINT lpFlags,
LPVOID lpFrom, LPINT lpFromlen, LPWSAOVERLAPPED
lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine, int FAR * lpErrno );
s A descriptor identifying an
overlapped, connected socket. which
was created using WSPSocket() with
flag WSA_FLAG_OVERLAPPED.
lpBuffer A pointer to the buffer for the
incoming data.
nNumberOfBytesToRecv The number of bytes to
receive from the network.
lpNumberOfBytesRecvd A pointer to the number
of bytes received by this call.
lpFlags A pointer to flags.
lpFrom An optional pointer to a buffer
which will hold the source address
upon the completion of the
overlapped operation.
lpFromlen An optional pointer to the size of
the from buffer.
lpOverlapped A pointer to a WSAOVERLAPPED
structure.
lpCompletionRoutine A pointer to the completion
routine called when the receive
operation has been completed.
lpErrno A pointer to the error code.
Remarks This function is used to post a buffer into which
incoming data will be placed as it becomes
available on a (possibly connected) socket. For
connectionless socket types, the address from
which the data originated is copied to the buffer
pointed by lpFrom. The value pointed to by
lpFromlen is initialized to the size of this
buffer, and is modified on return to indicate the
actual size of the address stored there. The
lpFrom and lpFromlen parameters are ignored for
connection-oriented sockets.
For non-overlapped socket, this function behaves
like the standard recvfrom() API with identical
blocking semantics. The lpOverlapped and
lpCompletionRoutine parameters are ignored. The
completion status of this SPI is the final
completion status of the receive operation.
For overlapped sockets, the final completion
status is retrieved via the
WSAGetOverlappedResult() API.
For byte stream style sockets (e.g., type
SOCK_STREAM), incoming data is placed into the
buffer until the buffer is filled. For message-
oriented sockets, an incoming message is placed
into the supplied buffer, up to the size of the
buffer supplied. If the message is larger than the
buffer supplied, the buffer is filled with the
first part of the message, the excess data is
lost, and WSPRecvFromWSPrecvfrom()
indicatesreturns the error code WSAEMSGSIZE.
If no incoming data is available at the socket,
the recvfrom() call waits for data to arrive
unless the socket is non-blocking. In this case a
value of SOCKET_ERROR is returned with the error
code set to WSAEWOULDBLOCK. The select(),
WSAAsyncSelect() or WSACallbackSelect() may be
used to determine when more data arrives.
If the socket is connection-oriented and the
remote side has shut down the connection
gracefully, a WSPRecvFromWSPrecvfrom() will
complete immediately with 0 bytes received. If the
connection has been reset WSPRecvFromWSPrecvfrom()
will fail with the error WSAECONNRESET.
This function may be called from within the
completion routine of a previous WSPRecvWSPrecv(),
WSPRecvFromWSPrecvfrom(), WSPSendWSPsend() or
WSPSendToWSPsendto() function.
When called with an overlapped socket, the
lpOverlapped parameter much be valid for the
duration of the overlapped operation. The
WSAOVERLAPPED structure has the following form:
typedef struct _WSAOVERLAPPED {
DWORD Internal; //
reserved
DWORD InternalHigh; //
reserved
DWORD Offset; // ignored
DWORD OffsetHigh; //
ignored
WSAEVENT hEvent;
} WSAOVERLAPPED, LPWSAOVERLAPPED;
If the lpCompletionRoutine parameter is NULL, the
hEvent field of lpOverlapped must be an event
object handle which is signaled when the
overlapped operation completes. An application can
use WSAWaitForMultipleEvents() or
WSAGetOverlappedResult() to wait or poll on the
event object.
The lpCompletionRoutine must be non-NULL and the
hEvent field is used to pass context information
to the completion routine.
The prototype of the completion routine is as
follows:
VOID CALLBACK CompletionRoutine( SOCKET s,
DWORD dwError, DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped );
CompletionRoutine is a placeholder for an
application-defined or library-defined function
pointername. dwError specifies the completion
status for the overlapped operation as indicated
by lpOverlapped. cbTransferred specifies the
number of bytes received. This function does not
return a value.
Returning from this function allows invocation of
another pending completion routine for this
socket. In Win32 environments, all waiting
completion routines are called before the
alterable thread's wait is satisfied with a return
code of WSA_IO_COMPLETION. The completion routines
may be called in any order, not necessarily in the
same order the overlapped operations are
completed. However, the posted buffers are
guaranteed to be filled in the same order they are
supplied
Flags may be used to influence the behavior of the
function invocation beyond the options specified
for the associated socket. That is, the semantics
of this function are determined by the socket
options and the flags parameter. The latter is
constructed by or-ing any of the following values:
Value Meaning
MSG_PEEK Peek at the incoming data. The data is
copied into the buffer but is not
removed from the input queue.
MSG_OOB Process out-of-band data (See section
for a discussion of this topic.)
Upon the completion of the overlapped operation,
the lpNumberOfBytesRecvd parameter is filled with
the number of bytes received, and, for message-
oriented sockets, the MSG_PARTIAL bit is set in
the lpFlags parameter if a partial message is
received. If a complete message is received,
MSG_PARTIAL is cleared in lpFlags.
Return Value If no error occurs, WSPRecvFromWSPrecvfrom()
returns the number of bytes received. If the
connection has been closed, it returns0.
Otherwise, a value of SOCKET_ERROR is returned,
and a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEFAULT The lpFromlen argument was
invalid: the lpFrom buffer was
too small to accommodate the
peer address.
WSAEINTR The (blocking) call was
canceled via
WSACancelBlockingCall().
WSAEINPROGRESS A blocking PII operation is in
progress.
WSAEINVAL The socket has not been bound
with WSPBindWSPbind(), or the
socket is not created with the
overlapped flag.
WSAENETRESET The connection must be reset
because the Winsock provider
dropped it.
WSAENOTCONN The socket is not connected
(connection-oriented sockets
only).
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP MSG_OOB was specified, but the
socket is not stream style
such as type SOCK_STREAM, out-
of-band data is not supported
in the communication domain
associated with this socket,
or the socket is
unidirectional and supports
only send operations.
WSAESHUTDOWN The socket has been shutdown;
it is not possible to
WSPRecvFromWSPrecvfrom() on a
socket after shutdown() has
been invoked with how set to
SD_RECEIVE or SD_BOTH.
WSAEWOULDBLOCK There are too many outstanding
overlapped I/O requests.
WSAEMSGSIZE The message was too large to
fit into the specified buffer
and was truncated. Any
trailing portion of the
message that did not fit into
the buffer has been discarded.
{Does this make sense?}
WSAECONNABORTED The virtual circuit was
aborted due to timeout or
other failure.
WSAECONNRESET The virtual circuit was reset
by the remote side.
See Also WSPSocket()
W3.1.2.212 WSPSendWSPsend()
Description Send data on a connected socket.
#include <ws2spi.h>
int WSPAPI WSPSendWSPsend ( SOCKET s, LPVOID
lpBuffer, DWORD nNumberOfBytesToSend, LPDWORD
lpNumberOfBytesSent, int nFlags, LPWSAOVERLAPPED
lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine, int FAR * lpErrno );
s A descriptor identifying an
overlapped, connected socket. which
was created using WSPSocket() with
flag WSA_FLAG_OVERLAPPED.
lpBuffer A pointer to the buffer for the
outgoing data.
nNumberOfBytesToSend The number of bytes to
send to the network.
lpNumberOfBytesSent A pointer to the number of
bytes sent by this call.
iFlags Flags.
lpOverlapped A pointer to a WSAOVERLAPPED
structure.
lpCompletionRoutine A pointer to the completion
routine called when the send
operation has been completed.
lpErrno A pointer to the error code.
Remarks WSPSendWSPsend() is used to write outgoing data on
an overlapped, connected socket asynchronously.
For message-oriented sockets, it is an error care
must be taken not to exceed the maximum packet
size of the underlying transportprovider, which
can be obtained by getting the value of socket
option SO_MAX_DG_SIZE. If the data is too long to
pass atomically through the underlying protocol
the error WSAEMSGSIZE is returned, and no data is
transmitted.
Note that the successful completion of a
WSPSendWSPsend() does not indicate that the data
was successfully delivered.
For non-overlapped socket, this function behaves
like the standard send() API with identical
blocking semantics. The lpOverlapped and
lpCompletionRoutine parameters are ignored. The
completion status of this SPI is the final
completion status of the receive operation.
For overlapped sockets, the final completion
status is retrieved via the
WSAGetOverlappedResult() API.
If no buffer space is available within the
transport system to hold the data to be
transmitted, send() will block unless the socket
has been placed in a non-blocking I/O mode. On
non-blocking stream-oriented sockets, the number
of bytes written may be between 1 and the
requested length, depending on buffer availability
on both the local and foreign hosts. The
select(), WSAAsyncSelect() or WSACallbackSelect()
call may be used to determine when it is possible
to send more data.
This function may be called from within the
completion routine of a previous WSPRecvWSPrecv(),
WSPRecvFromWSPrecvfrom(), WSPSendWSPsend() or
WSPSendToWSPsendto() function.
When called with an overlapped socket, the
lpOverlapped parameter much be valid for the
duration of the overlapped operation. The
WSAOVERLAPPED structure has the following form:
typedef struct _WSAOVERLAPPED {
DWORD Internal; //
reserved
DWORD InternalHigh; //
reserved
DWORD Offset; // ignored
DWORD OffsetHigh; //
ignored
WSAEVENT hEvent;
} WSAOVERLAPPED, LPWSAOVERLAPPED;
If the lpCompletionRoutine parameter is NULL, the
hEvent field of lpOverlapped must be an event
object handle which is signaled when the
overlapped operation completes. An application can
use WSAWaitForMultipleEvents() or
WSAGetOverlappedResult() to wait or poll on the
event object.
The lpCompletionRoutine must be non-NULL and the
hEvent field is used to pass context information
to the completion routine.
The prototype of the completion routine is as
follows:
VOID CALLBACK CompletionRoutine( SOCKET s,
DWORD dwError, DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped );
CompletionRoutine is a placeholder for an
application-defined or library-defined function
pointername. dwError specifies the completion
status for the overlapped operation as indicated
by lpOverlapped. cbTransferred specifies the
number of bytes received. This function does not
return a value.
Returning from this function allows invocation of
another pending completion routine for this
socket. In Win32 environments, all waiting
completion routines are called before the
alterable thread's wait is satisfied with a return
code of WSA_IO_COMPLETION. The completion routines
may be called in any order, not necessarily in the
same order the overlapped operations are
completed. However, the posted buffers are
guaranteed to be sent in the same order they are
supplied
Flags may be used to influence the behavior of the
function invocation beyond the options specified
for the associated socket. That is, the semantics
of this function are determined by the socket
options and the flags parameter. The latter is
constructed by or-ing any of the following values:
Value Meaning
MSG_DONTROUTE
Specifies that the data should not be
subject to routing. A Winsock service
provider may choose to ignore this flag;
see also the discussion of the
SO_DONTROUTE option in section
2.8.42.8.42.8.4.
MSG_OOB Send out-of-band data (stream style
socket such as SOCK_STREAM only; see
also section)
MSG_PARTIAL Specifies that lpBuffer only
contains a partial message. Note that
this flag will be ignored by transports
which do not support partial message
transmissions.
Upon the completion of the overlapped operation,
the lpNumberOfBytesSent parameter is filled with
the number of bytes sent.
MSG_INTERRUPT
Specifies that this function is being
called in interrupt context.
Return Value If no error occurs, WSPSendWSPsend() returns
0. the total number of characters sent. (Note
that this may be less than the number indicated by
len.) Otherwise, a value of SOCKET_ERROR is
returned, and a specific error code is available
in lpErrno.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEACCES The requested address is a
broadcast address, but the
appropriate flag was not set.
WSAEINTR The (blocking) call was
canceled via
WSACancelBlockingCall().
WSAEINPROGRESS A blocking PII operation is in
progress.
WSAEFAULT The lpBuffer argument is not
in a valid part of the user
address space.
WSAENETRESET The connection must be reset
because the Winsock provider
dropped it.
WSAENOBUFS The Winsock provider reports a
buffer deadlock.
WSAENOTCONN The socket is not connected.
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP MSG_OOB was specified, but the
socket is not stream style
such as type SOCK_STREAM, out-
of-band data is not supported
in the communication domain
associated with this socket,
or the socket is
unidirectional and supports
only receive operations.
WSAESHUTDOWN The socket has been shutdown;
it is not possible to
WSPSendWSPsend() on a socket
after WSPShutdownWSPshutdown()
has been invoked with how set
to SD_SEND or SD_BOTH.
WSAEWOULDBLOCK There are too many outstanding
overlapped I/O requests.
WSAEMSGSIZE The socket is message-
oriented, and the message is
larger than the maximum
supported by the underlying
transport.
WSAEINVAL The socket has not been bound
with WSPBindWSPbind(), or the
socket is not created with the
overlapped flag.
WSAECONNABORTED The virtual circuit was
aborted due to timeout or
other failure.
WSAECONNRESET The virtual circuit was reset
by the remote side.
See Also WSPSocket()
3.1.2.213 WSPSendToWSPsendto()
Description Send data to a specific destination using
overlapped I/O.
#include <ws2spi.h>
int WSPAPI WSPSendToWSPsendto ( SOCKET s, LPVOID
lpBuffer, DWORD nNumberOfBytesToSend, LPDWORD
lpNumberOfBytesSent, int nFlags, LPVOID lpTo, int
nTolen, LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine, int FAR * lpErrno );
s A descriptor identifying an
overlapped, connected socket which
was created using WSPSocket() with
flag WSA_FLAG_OVERLAPPED.
lpBuffer A pointer to the buffer for the
outgoing data.
nNumberOfBytesToSend The number of bytes to
send to the network.
lpNumberOfBytesSent A pointer to the number of
bytes sent by this call.
iFlags Flags.
lpTo An optional pointer to the address
of the target socket.
iTolen The size of the address in lpTo.
lpOverlapped A pointer to a WSAOVERLAPPED
structure.
lpCompletionRoutine A pointer to the completion
routine called when the send
operation has been completed.
lpErrno A pointer to the error code.
Remarks WSPSendToWSPsendto() is used to write outgoing
data on an overlapped socket asynchronously. For
message-oriented sockets, it is an errorcare must
be taken not to exceed the maximum packet size of
the underlying transportsubnets, which can be
obtained by getting the value of socket option
SO_MAX_DG_SIZE. If the data is too long to pass
atomically through the underlying protocol the
error WSAEMSGSIZE is returned, and no data is
transmitted.
Note that the successful completion of a
WSPSendToWSPsendto() does not indicate that the
data was successfully delivered.
For non-overlapped socket, this function behaves
like the standard sendto() API with identical
blocking semantics. The lpOverlapped and
lpCompletionRoutine parameters are ignored. The
completion status of this SPI is the final
completion status of the receive operation.
For overlapped sockets, the final completion
status is retrieved via the
WSAGetOverlappedResult() API.
WSPSendToWSPsendto() is normally used on a
connectionless socket to send a datagram to a
specific peer socket identified by the lpTo
parameter. On a connection-oriented socket, the
lpTo and iTolen parameters are ignored; in this
case the WSPSendToWSPsendto() is equivalent to
WSPSendWSPsend().
This function may be called from within the
completion routine of a previous WSPRecvWSPrecv(),
WSPRecvFromWSPrecvfrom(), WSPSendWSPsend() or
WSPSendToWSPsendto() function.
When called with an overlapped socket, the
lpOverlapped parameter much be valid for the
duration of the overlapped operation. The
WSAOVERLAPPED structure has the following form:
typedef struct _WSAOVERLAPPED {
DWORD Internal; //
reserved
DWORD InternalHigh; //
reserved
DWORD Offset; // ignored
DWORD OffsetHigh; //
ignored
WSAEVENT hEvent;
} WSAOVERLAPPED, LPWSAOVERLAPPED;
If the lpCompletionRoutine parameter is NULL, the
hEvent field of lpOverlapped must be an event
object handle which is signaled when the
overlapped operation completes. An application can
use WSAWaitForMultipleEvents() or
WSAGetOverlappedResult() to wait or poll on the
event object.
The lpCompletionRoutine must be non-NULL and the
hEvent field is used to pass context information
to the completion routine.
The prototype of the completion routine is as
follows:
VOID CALLBACK CompletionRoutine( SOCKET s,
DWORD dwError, DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped );
CompletionRoutine is a placeholder for an
application-defined or library-defined function
pointername. dwError specifies the completion
status for the overlapped operation as indicated
by lpOverlapped. cbTransferred specifies the
number of bytes received. This function does not
return a value.
Returning from this function allows invocation of
another pending completion routine for this
socket. In Win32 environments, all waiting
completion routines are called before the
alterable thread's wait is satisfied with a return
code of WSA_IO_COMPLETION. The completion routines
may be called in any order, not necessarily in the
same order the overlapped operations are
completed. However, the posted buffers are
guaranteed to be sent in the same order they are
supplied
Flags may be used to influence the behavior of the
function invocation beyond the options specified
for the associated socket. That is, the semantics
of this function are determined by the socket
options and the flags parameter. The latter is
constructed by or-ing any of the following values:
Value Meaning
MSG_DONTROUTE
Specifies that the data should not be
subject to routing. A WINSOCK service
provider may choose to ignore this flag;
see also the discussion of the
SO_DONTROUTE option in section
2.8.42.8.42.8.4.
MSG_OOB Send out-of-band data (stream style
socket such as SOCK_STREAM only; see
also section)
MSG_PARTIAL Specifies that lpBuffer only
contains a partial message. Note that
this flag will be ignored by transports
which do not support partial message
transmissions.
Upon the completion of the overlapped operation,
the lpNumberOfBytesSent parameter is filled with
the number of bytes sent.
Return Value If no error occurs, WSPSendToWSPsendto()
returns 0. Otherwise, a value of SOCKET_ERROR is
returned, and a specific error code is available
in lpErrno.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEACCES The requested address is a
broadcast address, but the
appropriate flag was not set.
WSAEINTR The (blocking) call was
canceled via
WSACancelBlockingCall().
WSAEINPROGRESS A blocking PII operation is in
progress.
WSAEFAULT The lpBuffer or lpTo
parameters are not part of the
user address space, or the
lpTo argument is too small
(less than the sizeof a struct
sockaddr).
WSAENETRESET The connection must be reset
because the Winsock provider
dropped it.
WSAENOBUFS The Winsock provider reports a
buffer deadlock.
WSAENOTCONN The socket is not connected
(connection-oriented sockets
only)
WSAENOTSOCK The descriptor is not a
socket.
WSAEOPNOTSUPP MSG_OOB was specified, but the
socket is not stream style
such as type SOCK_STREAM, out-
of-band data is not supported
in the communication domain
associated with this socket,
or the socket is
unidirectional and supports
only receive operations.
WSAESHUTDOWN The socket has been shutdown;
it is not possible to
WSPSendToWSPsendto() on a
socket after
WSPShutdownWSPshutdown() has
been invoked with how set to
SD_SEND or SD_BOTH.
WSAEWOULDBLOCK There are too many outstanding
overlapped I/O requests.
WSAEMSGSIZE The socket is message-
oriented, and the message is
larger than the maximum
supported by the underlying
transport.
WSAEINVAL The socket has not been bound
with WSPBindWSPbind(), or the
socket is not created with the
overlapped flag.
WSAECONNABORTED The virtual circuit was
aborted due to timeout or
other failure.
WSAECONNRESET The virtual circuit was reset
by the remote side.
WSAEADDRNOTAVAIL The specified address is not
available from the local
machine.
WSAEAFNOSUPPORT Addresses in the specified
family cannot be used with
this socket.
WSAEDESTADDRREQ A destination address is
required.
WSAENETUNREACH The network can't be reached
from this host at this time.
See Also WSPSocket()
3.1.2.214 WSPSetBlockingHook32()
Description Establish an application-specific blocking
hook function.
#include <ws2spi.h>
LPBLOCKINGPRC WSPAPI WSPSetBlockingHook32 (
LPBLOCKINGPROC lpBlockFunc, int FAR * lpErrno );
lpBlockFunc A pointer toot the procedure
instance address of the blocking
function to be installed.
lpErrno A pointer to the error code.
Remarks This function is only applicable to the 32-bit
SPIis only available in the 32-bit SPI.
This function installs a new function which the
Winsock Service Provider should use to implement
blocking socket function calls.
Winsock Service Providers include a default
mechanism by which blocking socket functions are
implemented. The function WSPSetBlockingHook32()
gives the application the ability to execute its
own function at "blocking" time in place of the
default function.
When an application invokes a blocking Windows
Sockets API operation, the Winsock Service
Provider initiates the operation and then enters a
loop which is similar to the following pseudocode:
for(;;) {
/* flush messages for good user response */
while(BlockingHook())
;
/* check for WSPCancelBlockingCall32() */
if(operation_cancelled())
break;
/* check to see if operation completed */
if(operation_complete())
break; /* normal completion */
}
Note that Winsock Service Providers may perform
the above steps in a different order; for example,
the check for operation complete may occur before
calling the blocking hook. The default
BlockingHook() function is equivalent to:
BOOL DefaultBlockingHook(void) {
MSG msg;
BOOL ret;
/* get the next message if any */
ret =
(BOOL)PeekMessage(&msg,NULL,0,0,PM_REMOVE);
/* if we got one, process it */
if (ret) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/* TRUE if we got a message */
return ret;
}
The WSPSetBlockingHook32() function is provided to
support those applications which require more
complex message processing - for example, those
employing the MDI (multiple document interface)
model. It is not intended as a mechanism for
performing general applications functions. In
particular, the only Windows Sockets SPI function
which may be issued from a custom blocking hook
function is WSPCancelBlockingCall32(), which will
cause the blocking loop to terminate.
This function must be implemented on a per-thread
basis for multithreaded versions of Windows such
as Windows NT. It thus provides for a particular
thread to replace the blocking mechanism without
affecting other threads.
In multithreaded versions of Windows, there is no
default blocking hook--blocking calls block the
thread that makes the call. However, an
application may install a specific blocking hook
by calling WSPSetBlockingHook32(). This allows
easy portability of applications that depend on
the blocking hook behavior.
Return Value The return value is a pointer to the
procedure-instance of the previously installed
blocking function. The Winsock DLL should save
this return value so that it can be restored if
necessary. (If "nesting" is not important, the
Winsock DLL may simply discard the value returned
by WSPSetBlockingHook32() and eventually use
WSPUnhookBlockingHook32() to restore the default
mechanism.) If the operation fails, a NULL pointer
is returned, and a specific error code is
available in lpErrno.
On a blocking socket, the return value indicates
success or failure of the connection attempt.
Comments Attempting to call PSCleanup() from within a
blocking hook and then failing to check the return
code is a common PII programming error. If an
application needs to quit while a blocking call is
outstanding, the application must first cancel the
blocking call with PSCancelBlockingCall() then
issue the PSCleanup() call once control has been
returned to the application.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The Windows Sockets
implementation has detected
that the network subsystem has
failed.
WSAEINPROGRESS A blocking Windows Sockets
operation is in progress.
WSANOTINITIALISED A successful PSStartup() must
occur before using this SPI.
See Also WSPCancelBlockingCall32(), WSPIsBlocking32(),
WSPUnhookBlockingHook32()
3.1.2.215 WSPSocket()
Description Create a socket which is bound to a specific
transport service provider.
{ May be revised to use PROTOCOL_INFO as an input param in
place of af, type, protocol parameters}
#include <ws2spiinsock2.h>
SOCKET WSPAPI WSPSocket ( int af, int type, int
protocol, DWORD dwProviderId, int nFlags, int FAR
* lpErrno );
af An address family specification. The
only format currently supported is
PF_INET, which is the ARPA Internet
address format.
type A type specification for the new socket.
protocol A particular protocol to be used with
the socket, or 0 if the caller does not
wish to specify a protocol.
dwProviderId An opaque value returned by the
WSAEnumProtocolsEnumProtocols() API that
identifies a unique service provider.
This information is useful to provider
implementations that present multiple
service provider appearances to Winsock.
iFlags The socket attribute specification.
lpErrno A pointer to the error code.
Remarks WSPSocket() causes a socket descriptor and any
related resources to be allocated and bound to the
transport service provider specified by
dwProviderId. If protocol is not specified (i.e.,
equal to zero), the default for the specified
socket type is used. However, the address family
may be given as AF_UNSPEC (unspecified), in which
case the protocol parameter must be specified. The
protocol number to use is particular to the
"communication domain'' in which communication is
to take place.
{The new name res stuff should obviate the need to
enumerate the list of supported socket types here}
The following type specifications may be supported
(all sockets are bi-directional unless specified
otherwise):
Type Explanation
SOCK_STREAM Alias for
SOCK_REL_STREAM.
SOCK_DGRAM Alias for
SOCK_UNREL_DGRAM.
SOCK_SEQPACKET Alias for
SOCK_REL_DSTREAM.
SOCK_RAW Raw socket.
SOCK_REL_STREAM Connection-oriented
reliable, unduplicated,
sequenced, byte
streamwith an out-of-
band data transmission
mechanism. Uses TCP
for the Internet
address family.
SOCK_REL_DSTREAM Connection-oriented
reliable, unduplicated,
sequenced, message
streamwith an out-of-
band data transmission
mechanism.
SOCK_UNREL_DSTREAM Connection-oriented
unreliable,
unduplicated,
sequenced, message
streamwith an out-of-
band data transmission
mechanism.
SOCK_REL_UNISEND_DSTREAMConnection-oriented,
reliable, one-way (send
only), unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_REL_UNIRECV_DSTREA
M.
SOCK_REL_UNIRECV_DSTREAMConnection-oriented,
reliable, one-way
(receive only),
unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_REL_UNISEND_DSTREA
M.
SOCK_UNREL_UNISEND_DSTREAM Connection-
oriented, unreliable,
one-way (send only),
unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_UNREL_UNIRECV_DSTR
EAM.
SOCK_UNREL_UNIRECV_DSTREAM Connection-
oriented, unreliable,
one-way (receive only),
unduplicated,
sequenced, message
stream. The matching
socket at the remote
side need to be of
style
SOCK_UNREL_UNISEND_DSTR
EAM.
SOCK_REL_DGRAM Connectionless,
reliable, datagram.
SOCK_UNREL_DGRAM Connectionless,
unreliable, datagram.
SOCK_REL_ISOCH_DSTREAM Connection-oriented
reliable, unduplicated,
sequenced, isochronous,
message streamwith an
out-of-band data
transmission mechanism.
SOCK_UNREL_ISOCH_DSTREAMConnection-oriented
unreliable,
unduplicated,
sequenced, isochronous,
message streamwith an
out-of-band data
transmission mechanism.
SOCK_UNREL_ISOCH_STREAM Connection-oriented
unreliable,
unduplicated,
sequenced, isochronous,
byte streamwith an out-
of-band data
transmission mechanism.
The iFlags parameter may be used to specify the
attributes of the socket by or-ing any of the
following Flags:
Flag Meaning
WSA_FLAG_OVERLAPPED
This flag causes an overlapped socket to
be created. Overlapped sockets must
utilize the overlapped I/O features of
the WSPSendWSPsend(),
WSPSendToWSPsendto(), WSPRecvWSPrecv(),
WSPRecvFromWSPrecvfrom() SPI for I/O
operations, and allows multiple of these
to be initiated and in progress
simultaneously. Overlapped sockets are
always non-blocking.
Connection-oriented sockets such as SOCK_STREAM
provide full-duplex connections, and must be in a
connected state before any data may be sent or
received on it. A connection to another socket is
created with a connect() call. Once connected,
data may be transferred using WSPSendWSPsend() and
WSPRecvWSPrecv() calls. When a session has been
completed, a WSPCloseSocketWSPclosesocket() must
be performed. Out-of-band data may also be
transmitted as described in send() and received as
described in recv().
The communications protocols used to implement a
reliable, connection-oriented socket ensure that
data is not lost or duplicated. If data for which
the peer protocol has buffer space cannot be
successfully transmitted within a reasonable
length of time, the connection is considered
broken and subsequent calls will fail with the
error code set to WSAETIMEDOUT.
Connectionless, message-oriented sockets allow
sending and receiving of datagrams to and from
arbitrary peers using WSPSendToWSPsendto() and
WSPRecvFromWSPrecvfrom(). If such a socket is
connect()ed to a specific peer, datagrams may be
send to that peer using WSPSendWSPsend() and may
be received from (only) this peer using
WSPRecvWSPrecv().
Return Value If no error occurs, WSPSocket() returns a
descriptor referencing the new socket. Otherwise,
a value of INVALID_SOCKET is returned, and a
specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful WSPStartup() must
occur before using this SPI.
WSAENETDOWN The network subsystem has
failed.
WSAEAFNOSUPPORT The specified address family
is not supported.
WSAEINPROGRESS A blocking Winsock call is in
progress, or the service
provider is still processing a
callback function.
WSAEMFILE No more socket descriptors are
available.
WSAENOBUFS No buffer space is available.
The socket cannot be created.
WSAEPROTONOSUPPORT The specified protocol is not
supported.
WSAEPROTOTYPE The specified protocol is the
wrong type for this socket.
WSAESOCKTNOSUPPORT The specified socket type is
not supported in this address
family.
See Also WSPAccept, WSPBindWSPbind(), WSPConnect(),
WSPGetSockNameWSPgetsockname(),
WSPGetSockOptWSPgetsockopt(),
WSPSetSockOptWSPsetsockopt(),
WSPListenWSPlisten(), WSPRecvWSPrecv(),
WSARecvFrom(), WSASend(), WSASendToWSASentTo(),
WSPShutdownWSPshutdown(),
WSPIoctlSocketWSPioctlsocket().
3.1.2.216 WSPStartup()
Description
#include <ws2spi.h>
int WSPAPI WSPStartup ( WORD wVersionRequested,
LPWSADATA lpWSAData );
wVersionRequested The highest version of Winsock
SPI support that the caller can
use. The high order byte specifies
the minor version (revision)
number; the low-order byte
specifies the major version number.
lpWSAData A pointer to the WSADATA data
structure that is to receive
details of the Winsock service
provider.
Remarks This function MUST be the first Winsock SPI
function called by the Winsock DLL. It allows the
Winsock DLL to specify the version of Winsock SPI
required and to retrieve details of the specific
Winsock service provider implementation. The
Winsock DLL may only issue further Winsock SPI
functions after a successful WSPStartup()
invocation.
In order to support future Winsock service
providers and the Winsock DLL which may have
functionality differences from the current Winsock
SPI, a negotiation takes place in WSPStartup().
The caller of WSPStartup() (namely, the Winsock
DLL) and the Winsock service provider indicate to
each other the highest version that they can
support, and each confirms that the other's
highest version is acceptable. Upon entry to
WSPStartup(), the Winsock service provider
examines the version requested by the Winsock DLL.
If this version is higher than the lowest version
supported by the service provider, the call
succeeds and the service provider returns in
wHighVersion the highest version it supports and
in wVersion the minimum of its high version and
wVersionRequested. The Winsock service provider
then assumes that the Winsock DLL will use
wVersion. If the wVersion field of the WSADATA
structure is unacceptable to the caller, it should
call WSPCleanup() and either search for another
Winsock service provider or fail to initialize.
This negotiation allows both a Winsock service
provider and the Winsock DLL to support a range of
Winsock versions. The Winsock DLL can successfully
utilize a Winsock service provider if there is any
overlap in the version ranges. The following chart
gives examples of how WSPStartup() works in
conjunction with different DLL and Winsock service
provider (SP) versions:
DLL SP wVersionR wVer wHighV End Result
versio Versio equested sion ersion
ns ns
1.1 1.1 1.1 1.1 1.1 use 1.1
1.0 1.0 1.1 1.0 1.0 use 1.0
1.1
1.0 1.0 1.1 1.0 1.0 1.1 use 1.0
1.1 1.0 1.1 1.1 1.1 use 1.1
1.1
1.1 1.0 1.1 1.0 1.0 DLL fails
1.0 1.1 1.0 --- --- WSAVERNOTSUPPO
RTED
1.0 1.0 1.1 1.1 1.1 use 1.1
1.1 1.1
1.1 1.1 2.0 1.1 1.1 use 1.1
2.0
2.0 1.1 2.0 1.1 1.1 DLL fails
The following code fragment demonstrates how a DLL
which supports only version 1.1 of Winsock SPI
makes a WSPStartup() call:
WORD wVersionRequested;
WSADATA WSAData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSPStartup( wVersionRequested, &WSAData );
if ( err != 0 ) {
/* Tell the user that we couldn't find a
useable */
/* Winsock service provider.
*/
return;
}
/* Confirm that the Winsock service provider
supports 1.1.*/
/* Note that if the service provider supports
versions greater */
/* than 1.1 in addition to 1.1, it will still
return */
/* 1.1 in wVersion since that is the version we
*/
/* requested.
*/
if ( LOBYTE( WSAData.wVersion ) != 1 ||
HIBYTE( WSAData.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a
useable */
/* Winsock service provider.
*/
WSPCleanup( );
return;
}
/* The Winsock service provider is acceptable.
Proceed. */
And this code fragment demonstrates how a Winsock
service provider which supports only version 1.1
performs the WSPStartup() negotiation:
/* Make sure that the version requested is >= 1.1.
*/
/* The low byte is the major version and the high
*/
/* byte is the minor version.
*/
if ( LOBYTE( wVersionRequested ) < 1 ||
( LOBYTE( wVersionRequested ) == 1 &&
HIBYTE( wVersionRequested ) < 1 ) {
return WSAVERNOTSUPPORTED;
}
/* Since we only support 1.1, set both wVersion
and */
/* wHighVersion to 1.1.
*/
lpWSAData->wVersion = MAKEWORD( 1, 1 );
lpWSAData->wHighVersion = MAKEWORD( 1, 1 );
Once the Winsock DLL has made a successful
WSPStartup() call, it may proceed to make other
Winsock SPI calls as needed. When it has finished
using the services of the Winsock service
provider, the Winsock DLL must call WSPCleanup()
in order to allow the Winsock service provider to
free any resources for the Winsock DLL.
Details of the actual Winsock service provider are
described in the WSAData structure defined as
follows:
{If we remove iMaxSockets & iMaxUdpDg, should we
rename the structure to WSAData2 to avoid
confusion with the Winsock 1.1 WSAData?}
struct WSAData {
WORD wVersion;
WORD wHighVersion;
char
szDescription[WSADESCRIPTION_LEN+1];
char
szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
};
The members of this structure are:
Element Usage
wVersion The version of the Winsock SPI
specification that the Winsock service
provider expects the caller to use.
wHighVersion The highest version of the Winsock
SPI specification that this service
provider can support (also encoded as
above). Normally this will be the same
as wVersion.
szDescription A null-terminated ASCII string into
which the Winsock DLL copies a
description of the Winsock service
provider. The text (up to 256 characters
in length) may contain any characters
except control and formatting
characters: the most likely use that an
application will put this to is to
display it (possibly truncated) in a
status message.
szSystemStatus A null-terminated ASCII string into
which the Winsock service provider
copies relevant status or configuration
information. The Winsock service
provider should use this field only if
the information might be useful to the
user or support staff: it should not be
considered as an extension of the
szDescription field.
iMaxSockets The maximum number of sockets which
a single process can potentially open. A
Winsock service provider may provide a
global pool of sockets for allocation to
any process; alternatively it may
allocate per-process resources for
sockets. The number may well reflect the
way in which the Winsock service
provider or the networking software was
configured. Application writers may use
this number as a crude indication of
whether the Winsock service provider is
usable by the application. For example,
an X Windows server might check
iMaxSockets when first started: if it is
less than 8, the application would
display an error message instructing the
user to reconfigure the networking
software. (This is a situation in which
the szSystemStatus text might be used.)
Obviously there is no guarantee that a
particular application can actually
allocate iMaxSockets sockets, since
there may be other Winsock applications
in use.
iMaxUdpDg This value is retained for compatibility
with Windows Sockets specification 1.1,
but should not be used when developing
new applications. The value supplied
here will always be 512, the minimum
allowed. For the actual maximum message
size specific to a particular Winsock
service provider and socket type, the
Winsock DLL should use
WSPGetSockOptWSPgetsockopt() to retrieve
the value of option SO_MAX_DG_SIZE after
a socket has been created. The minimum
value of iMaxUdpDg for a compliant PII
implementation is 512. Note that
regardless of the value of iMaxUdpDg, it
is inadvisable to attempt to send a
broadcast datagram which is larger than
the Maximum Transmission Unit (MTU) for
the network. (The PII does not provide
a mechanism to discover the MTU, but it
must be no less than 512 bytes.)
lpVendorInfo This value should be ignored. It is
retained for compatibility with Windows
Sockets specification 1.1. The Winsock
DLL needing to access vendor-specific
configuration information should use
WSPGetSockOptWSPgetsockopt() to retrieve
the value of option PVD_CONFIG. The
definition of this value (if utilized)
is beyond the scope of this
specification.
A PII.DLL may call PSStartup() more than once if
it needs to obtain the WSAData structure
information more than once. However, the
wVersionRequired parameter is assumed to be the
same on all calls to PSStartup(); that is, a
PII.DLL cannot change the version of PII SPI it
expects after the initial call to PSStartup().
There must be one PSCleanup() call corresponding
to every PSStartup() call to allow third-party
DLLs to make use of a PII.DLL on behalf of an
application. This means, for example, that if an
application calls PSStartup() three times, it must
call PSCleanup() three times. The first two calls
to PSCleanup() do nothing except decrement an
internal counter; the final PSCleanup() call for
the task does all necessary resource deallocation
for the task.
Return Value WSPStartup() returns zero if successful.
Otherwise it returns one of the error codes listed
below. Note that the normal mechanism whereby the
application calls PSGetLastError() to determine
the error code cannot be used, since the PII.DLL
may not have established the client data area
where the "last error" information is stored.
Notes For
Winsock Service
Providers The Winsock DLL will make one and only one
WSPStartup() call before issuing any other Winsock
SPI calls for each Winsock service provider. This
function can thus be utilized for initialization
purposes.
Further issues are discussed in the notes for
WSPCleanup().
Error Codes WSASYSNOTREADY Indicates that
the underlying network
subsystem is not ready for
network communication.
WSAVERNOTSUPPORTED The version of Winsock SPI
support requested is not
provided by this particular
Winsock service provider.
WSAEFAULT The lpWSAData parameter is
invalid.
WSAEINVAL The PII version specified by
the application is not
supported by this DLL.
See Also WSPSendWSPsend(), WSPSendToWSPsendto(),
WSPCleanup()
3.1.2.217 WSPUnhookBlockingHook32()
Description Restores the default blocking hook function.
#include <ws2spi.h>
int WSPAPI WSPUnhookBlockingHook32 ( int FAR *
lpErrno );
lpErrno A pointer to the error code.
Remarks This function is only applicable to the 32-bit
SPIis only available in the 32-bit SPI.
This function removes any previous blocking hook
that has been installed and reinstalls the default
blocking mechanism.
This function is only applicable to the 32-bit
SPIis only available in the 32-bit SPI.
WSPUnhookBlockingHook32() will always install the
default mechanism, not the previous mechanism. If
the Winsock DLL wishes to nest blocking hooks -
i.e. to establish a temporary blocking hook
function and then revert to the previous mechanism
(whether the default or one established by an
earlier WSPSetBlockingHook32()) - it must save and
restore the value returned by
WSPSetBlockingHook32(); it cannot use
WSPUnhookBlockingHook32().
In multithreaded versions of Windows such as
Windows NT, there is no default blocking hook.
Calling WSPUnhookBlockingHook32() disables any
blocking hook installed by the application and any
blocking calls made block the thread which made
the call.
Return Value The return value is 0 if the operation has
been successfully initiated. Otherwise the value
SOCKET_ERROR is returned, and a specific error
number is available in lpErrno.
On a blocking socket, the return value indicates
success or failure of the connection attempt.
Comments Attempting to call PSCleanup() from within a
blocking hook and then failing to check the return
code is a common PII programming error. If an
application needs to quit while a blocking call is
outstanding, the application must first cancel the
blocking call with PSCancelBlockingCall() then
issue the PSCleanup() call once control has been
returned to the application.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSANOTINITIALISED A successful WSPStartup() must
occur before using this SPI.
See Also WSPCancelBlockingCall32(), WSPIsBlocking32(),
WSPSetBlockingHook32()
4. Upcalls
This section contains the private "upcalls" that service
providers may make into the Windows Sockets DLL. All upcalls
are prefixed with "Xxx" to distinguish them from the normal
API and SPI entrypoints.
4.1 WPUXxxCreateSocketHandle()
Description Creates a new socket handle.
#include <ws2spi.h>
SOCKET WSPAPI WPUXxxCreateSocketHandle ( DWORD
dwProviderId, LPVOID lpContext, int FAR * lpErrno
);
dwProviderId Identifies the calling service
provider. {We must provide a mechanism
for getting this to the provider,
perhaps at WspStartup() time?}
lpContext A context value to associate with the
new socket handle.
lpErrno A pointer to the error code.
Remarks This routine creates a new socket handle for the
specified provider. The handle returned is Winsock
specific; it is not a proper system handle.
This routine is only used by providers that do not
provide real system handles.
Return Value If no error occurs,
WPUXxxCreateSocketHandle() returns the new socket
handle. Otherwise, it returns INVALID_SOCKET, and
a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENOBUFS Not enough buffers available,
too many sockets.
See Also WPUXxxCloseSocketHandle()PSCancelBlockingCall().
4.2 WPUXxxCloseSocketHandle()
Description Closes an existing socket handle.
#include <ws2spi.h>
int WSPAPI WPUXxxCloseSocketHandle ( SOCKET s, int
FAR * lpErrno );
s Identifies a socket handle created with
WPUXxxCreateSocketHandle().
lpErrno A pointer to the error code.
Remarks This routine closes an existing socket handle.
This function removes the socket from Winsock's
internal socket table. The owning service provider
is responsible for releasing any resources
associated with the socket.
Return Value If no error occurs,
WPUXxxCreateSocketHandle() returns 0. Otherwise,
it returns SOCKET_ERROR, and a specific error code
is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENOTSOCK The descriptor is not a socket
created by
WPUXxxCreateSocketHandle().
See Also WPUXxxCreateSocketHandle()PSCancelBlockingCall().
4.3 WPUXxxQuerySocketHandleContext()
Description Queries the context value associated with the
specified socket handle.
#include <ws2spi.h>
int WSPAPI WPUXxxQuerySocketHandleContext ( SOCKET
s, LPVOID FAR * lpContext, int FAR * lpErrno );
s Identifies the socket whose context is
to be queried.
lpContext A pointer to an LPVOID that will receive
the context value.
lpErrno A pointer to the error code.
Remarks This routine queries the current context value
associated with the specified socket handle.
Service providers typically use this function to
retrieve a pointer to provider-specific data
associated with the socket. For example, a service
provider may use the socket context to store a
pointer to a structure containing the socket's
state, local and remote transport addresses, event
objects for signaling network events, etc.
Return Value If no error occurs,
WPUXxxQuerySocketHandleContext() returns 0 and
stores the current context value in lpContext.
Otherwise, it returns SOCKET_ERROR, and a specific
error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENOTSOCK The descriptor is not a socket
created by
WPUXxxCreateSocketHandle().
See Also WPUXxxCreateSocketHandle(),
WPUXxxSetSocketHandleContext()PSCancelBlockingCall
().
4.4 WPUXxxSetSocketHandleContext()
Description Sets the context value associated with the
specified socket handle.
#include <ws2spi.h>
int WSPAPI WPUXxxSetSocketHandleContext ( SOCKET
s, LPVOID lpContext, int FAR * lpErrno );
s Identifies the socket whose context is
to be set.
lpContext The new context value to associate with
the socket.
lpErrno A pointer to the error code.
Remarks This routine sets the current context value
associated with the specified socket handle.
Return Value If no error occurs,
WPUXxxSetSocketHandleContext() returns 0 and
stores lpContext and the socket's new context
value. Otherwise, it returns SOCKET_ERROR, and a
specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
WSAENOTSOCK The descriptor is not a socket
created by
WPUXxxCreateSocketHandle().
See Also WPUXxxCreateSocketHandle(),
WPUXxxQuerySocketHandleContext()PSCancelBlockingCa
ll().
4.5 WPUXxxQueueUserAPC32()
Description Queues a user-mode APC against the specified
thread.
#include <ws2spi.h>
int WSPAPI WPUXxxQueueUserAPC32UserAPC ( DWORD
dwThreadId, LPWSAUSERAPC lpfnUserApc, DWORD
dwContext, int FAR * lpErrno );
dwThreadId Identifies the target thread for
the APC. This is typically a value
returned by the
WPUXxxGetCurrentThreadId() upcall.
lpfnUserApc Points to the function to be called
as a user-mode APC.
dwContext A context value to be passed in to the
user-mode APC function.
lpErrno A pointer to the error code.
Remarks This routine queues a user-mode APC against the
specified thread. The APC will only execute when
the specified thread is blocked in an alertable
wait. This function is only available in 32 bit
versions of the Winsock 2 DLL.
LPWSAUSERAPC is defined as follows:
typedef VOID (FAR * LPWSAUSERAPC)( DWORD
dwContext );
Return Value If no error occurs,
WPUXxxQueueUserAPC32UserAPC() returns 0 and queues
the APC for the specified thread. Otherwise, it
returns SOCKET_ERROR, and a specific error code is
available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
???? dwThreadId does not specify a
valid thread.
See Also WPUXxxGetCurrentThreadId32()PSCancelBlockingCall()
.
4.6 WPUXxxGetCurrentThreadId32()
Description Returns an operating-system specific
identifier for the current thread.
#include <ws2spi.h>
DWORD WSPAPI WPUXxxGetCurrentThreadId32 ( VOID );
Remarks This routine returns an operating-system specific
identifier for the current thread. The returned
value is suitable for use in the
WPUXxxQueueUserAPC32UserAPC() upcall.
Return Value WPUXxxGetCurrentThreadId32() returns the
current thread ID.
See Also WPUXxxQueueUserAPC32UserAPC()PSCancelBlockingCall(
).
5. Installation APIs
This section is super preliminary. These APIs will be
receive additional attention after the December 12th
meeting.
5.1 WPUInstallProvider()
Description Installs the specified provider into the
system configuration database.
#include <ws2spi.h>
int WSPAPI WPUInstallProvider( const char FAR *
lpszProviderName, const char FAR *
lpszProviderDllPath, const PROTOCOL_INFO FAR *
lpProtocolInfoList, DWORD dwNumberOfEntries, DWORD
FAR * lpdwProviderId, int FAR * lpErrno );
lpszProviderName Points to locally unique name
for this provider. This name must
not conflict with any currently
installed provider.
lpszProviderDllPath Points to a fully qualified
path to the provider's DLL image.
The Winsock DLL passes this path
into the LoadLibrary API to load
the provider.
lpProtocolInfoList Points to an array of
PROTOCOL_INFO structures. Each
structure defines a
protocol/address_family/socket_type
supported by the provider.
dwNumberOfEntries Contains the number of entries
in the lpProtocolInfoList array.
lpdwProviderId Points to a DWORD that will receive
the locally unique identifier for
the newly installed provider.
lpErrno A pointer to the error code.
Remarks This routine creates the necessary common Winsock
2 configuration information for the specified
provider. After this routine completes
successfully, the protocol information provided in
lpProtocolInfoList will be returned by the
WSAEnumProtocols API.
Any file installation or service provider specific
configuration information must be performed by the
provider setup application.
Return Value If no error occurs, WPUInstallProvider()
returns 0. Otherwise, it returns SOCKET_ERROR, and
a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
???? ????
See Also WPUDeinstallProvider(),
WSAEnumProtocols()PSCancelBlockingCall().
5.2 WPUDeinstallProvider()
Description Removes the specified provider from the
system configuration database.
#include <ws2spi.h>
int WSPAPI WPUDeinstallProvider( DWORD
dwProviderId, int FAR * lpErrno );
dwProviderId The locally unique identifier of
the provider to deinstall. This
must be a value previously returned
by WPUInstallProvider().
lpErrno A pointer to the error code.
Remarks This routine removes the common Winsock 2
configuration information for the specified
provider. After this routine completes
successfully, the protocol information associated
with the provider will not be returned by the
WSAEnumProtocols API.
Any file removal or service provider specific
configuration information removal must be
performed by the provider setup application.
Return Value If no error occurs, WPUDeinstallProvider()
returns 0. Otherwise, it returns SOCKET_ERROR, and
a specific error code is available in lpErrno.
Error Codes WSANOTINITIALISED A
successful PSStartup() must
occur before using this SPI.
???? ????
See Also WPUInstallProvider(),
WSAEnumProtocols()PSCancelBlockingCall().
Appendix A. Error Codes and Header Files
A.1 Error Codes
The following is a list of possible error codes available in
the lpErrno parameter of each function, along with their
explanations. The error numbers are consistently set across
all Winsock-compliant implementations.
Winsock code Berkeley Err Interpretation
equivalent or
WSAEINTR EINTR 100 As in standard C
04
WSAEBADF EBADF 100 As in standard C
09
WSAEACCES EACCES 100 As in standard C
13
WSAEFAULT EFAULT 100 As in standard C
14
WSAEINVAL EINVAL 100 As in standard C
22
WSAEMFILE EMFILE 100 As in standard C
24
WSAEWOULDBLOC EWOULDBLOCK 100 As in BSD
K 35
WSAEINPROGRES EINPROGRESS 100 This error is returned
S 36 if any
Winsock function is
called while a blocking
function is
in progress.
WSAEALREADY EALREADY 100 As in BSD
37
WSAENOTSOCK ENOTSOCK 100 As in BSD
38
WSAEDESTADDRR EDESTADDRREQ 100 As in BSD
EQ 39
WSAEMSGSIZE EMSGSIZE 100 As in BSD
40
WSAEPROTOTYPE EPROTOTYPE 100 As in BSD
41
WSAENOPROTOOP ENOPROTOOPT 100 As in BSD
T 42
WSAEPROTONOSU EPROTONOSUPPO 100 As in BSD
PPORT RT 43
WSAESOCKTNOSU ESOCKTNOSUPPO 100 As in BSD
PPORT RT 44
WSAEOPNOTSUPP EOPNOTSUPP 100 As in BSD
45
WSAEPFNOSUPPO EPFNOSUPPORT 100 As in BSD
RT 46
WSAEAFNOSUPPO EAFNOSUPPORT 100 As in BSD
RT 47
WSAEADDRINUSE EADDRINUSE 100 As in BSD
48
WSAEADDRNOTAV EADDRNOTAVAIL 100 As in BSD
AIL 49
WSAENETDOWN ENETDOWN 100 As in BSD. This error
50 may be reported at any
time if the Winsock
service provider
detects an underlying
failure.
WSAENETUNREAC ENETUNREACH 100 As in BSD
H 51
WSAENETRESET ENETRESET 100 As in BSD
52
WSAECONNABORT ECONNABORTED 100 As in BSD
ED 53
WSAECONNRESET ECONNRESET 100 As in BSD
54
WSAENOBUFS ENOBUFS 100 As in BSD
55
WSAEISCONN EISCONN 100 As in BSD
56
WSAENOTCONN ENOTCONN 100 As in BSD
57
WSAESHUTDOWN ESHUTDOWN 100 As in BSD
58
WSAETOOMANYRE ETOOMANYREFS 100 As in BSD
FS 59
WSAETIMEDOUT ETIMEDOUT 100 As in BSD
60
WSAECONNREFUS ECONNREFUSED 100 As in BSD
ED 61
WSAELOOP ELOOP 100 As in BSD
62
WSAENAMETOOLO ENAMETOOLONG 100 As in BSD
NG 63
WSAEHOSTDOWN EHOSTDOWN 100 As in BSD
64
WSAEHOSTUNREA EHOSTUNREACH 100 As in BSD
CH 65
WSASYSNOTREAD 100 Returned by
Y 91 WSPStartup()
indicating that the
network subsystem is
unusable.
WSAVERNOTSUPP 100 Returned by
ORTED 92 WSPStartup()
indicating that the
Winsock
service provider cannot
support the Winsock
DLL.
WSANOTINITIAL 100 Returned by any
ISED 93 function except
PSStartup() indicating
that a successful
PSStartup() has not yet
been performed.
WSAHOST_NOT_F HOST_NOT_FOUN 110 As in BSD.
OUND D 01
WSATRY_AGAIN TRY_AGAIN 110 As in BSD
02
WSANO_RECOVER NO_RECOVERY 110 As in BSD
Y 03
WSANO_DATA NO_DATA 110 As in BSD
04
The first set of definitions is present to resolve
contentions between standard C error codes which may be
defined inconsistently between various C compilers.
The second set of definitions provides Winsock versions of
regular Berkeley Sockets error codes.
The third set of definitions consists of extended Winsock-
specific error codes.
The error numbers are derived from the ws2spi.h header file
listed in section A.2A.2A.2, and are based on the fact that
Winsock error numbers are computed by adding 10000 to the
"normal" Berkeley error number.
Note that this table does not include all of the error codes
defined in ws2spi.h. This is because it includes only errors
which might reasonably be returned by a Winsock service
provider: ws2spi.h, on the other hand, includes a full set
of BSD definitions to ensure compatibility with ported
software.
A.2 Header Files
A.2.1 Berkeley Header Files
A PII service provider who provides a development kit to
support the development of PII applications must supply a
set of vestigial header files with names that match a number
of the header files in the Berkeley software distribution.
These files are provided for source code compatibility only,
and each consists of three lines:
#ifndef _PIISPI_
#include <PIISPI.h>
#endif
The header files provided for compatibility are:
netdb.h
arpa/inet.h
sys/time.h
sys/socket.h
netinet/in.h
The file PIISPI.h contains all of the type and structure
definitions, constants, macros, and function prototypes used
by the PII specification. An application writer may choose
to ignore the compatibility headers and include PIISPI.h in
each source file.
A.2 Winsock SPI Header File - ws2spi.h
The ws2spi.h header file includes a number of types and
definitions from the standard Windows header file windows.h.
The windows.h in the Windows 3.0 SDK (Software Developer's
Kit) lacks a #include guard, so if you need to include
windows.h as well as ws2spi.h, you should define the symbol
_INC_WINDOWS before #including ws2spi.h, as follows:
#include <windows.h>
#define _INC_WINDOWS
#include <ws2spi.h>
Users of the SDK for Windows 3.1 and later need not do this.
A Winsock service provider vendor MUST NOT make any
modifications to this header file which could impact binary
compatibility of Winsock applications. The constant values,
function parameters and return codes, and the like must
remain consistent across all Winsock service provider
vendors.
/* WS2SPI.H--definitions to be used with the Winsock service
provider.
*
* This header file corresponds to version 2.0 of the
Winsock SPI specification.
*
* This file includes parts which are Copyright (c) 1982-
1986 Regents
* of the University of California. All rights reserved.
The
* Berkeley Software License Agreement specifies the terms
and
* conditions for redistribution.
*/
#ifndef _WS2SPI_
#define _WS2SPI_
#ifndef _WS2API_
/*
* Pull in WINDOWS.H if necessary
*/
#ifndef _INC_WINDOWS
#include <windows.h>
#endif /* _INC_WINDOWS */
/*
* SPI function linkage.
*/
#define WSPAPI WSPAPI
/*
* Basic system type definitions, taken from the BSD file
sys/types.h.
*/
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
/*
* The new type to be used in all
* instances which refer to sockets.
*/
typedef u_int SOCKET;
/*
* Select uses arrays of SOCKETs. These macros manipulate
such
* arrays. FD_SETSIZE may be defined by the user before
including
* this file, but the default here should be >= 64.
*
* CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST
BE
* INCLUDED IN WS2SPI.H EXACTLY AS SHOWN HERE.
*/
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */
typedef struct fd_set {
u_short fd_count; /* how many are SET?
*/
SOCKET fd_array[FD_SETSIZE]; /* an array of
SOCKETs */
} fd_set;
#ifdef __cplusplus
extern "C" {
#endif
extern int WSPAPI __WSAFDIsSet(SOCKET, fd_set FAR *);
#ifdef __cplusplus
}
#endif
#define FD_CLR(fd, set) do { \
u_int __i; \
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ;
__i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == fd) { \
while (__i < ((fd_set FAR *)(set))->fd_count-1)
{ \
((fd_set FAR *)(set))->fd_array[__i] = \
((fd_set FAR *)(set))->fd_array[__i+1];
\
__i++; \
} \
((fd_set FAR *)(set))->fd_count--; \
break; \
} \
} \
} while(0)
#define FD_SET(fd, set) do { \
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) \
((fd_set FAR *)(set))->fd_array[((fd_set FAR
*)(set))->fd_count++]=fd;\
} while(0)
#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0)
#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)fd, (fd_set
FAR *)set)
/*
* Structure used in select() call, taken from the BSD file
sys/time.h.
*/
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
/*
* Operations on timevals.
*
* NB: timercmp does not work for >= or <=.
*/
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)-
>tv_usec)
#define timercmp(tvp, uvp, cmp) \
((tvp)->tv_sec cmp (uvp)->tv_sec || \
(tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec
cmp (uvp)->tv_usec)
#define timerclear(tvp) (tvp)->tv_sec = (tvp)-
>tv_usec = 0
/*
* Winsock extension
*/
#define MAKEWORD(low, high) ((WORD)(((BYTE)(low)) |
(((WORD)((BYTE)(high))) << 8)))
/*
* Commands for ioctlsocket(), taken from the BSD file
fcntl.h.
*
*
* Ioctl's have the command encoded in the lower word,
* and the size of any in or out parameters in the upper
* word. The high 2 bits of the upper word are used
* to encode the in/out status of the parameter; for now
* we restrict parameters to at most 128 bytes.
*/
#define IOCPARM_MASK 0x7f /* parameters must
be < 128 bytes */
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out
parameters */
#define IOC_IN 0x80000000 /* copy in
parameters */
#define IOC_INOUT (IOC_IN|IOC_OUT)
/* 0x20000000
distinguishes new &
old ioctl's */
#define _IO(x,y) (IOC_VOID|(x<<8)|y)
#define _IOR(x,y,t)
(IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define _IOW(x,y,t)
(IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define FIONREAD _IOR('f', 127, u_long) /* get # bytes to
read */
#define FIONBIO _IOW('f', 126, u_long) /* set/clear non-
blocking i/o */
#define FIOASYNC _IOW('f', 125, u_long) /* set/clear
async i/o */
/* Socket I/O Controls */
#define SIOCSHIWAT _IOW('s', 0, u_long) /* set high
watermark */
#define SIOCGHIWAT _IOR('s', 1, u_long) /* get high
watermark */
#define SIOCSLOWAT _IOW('s', 2, u_long) /* set low
watermark */
#define SIOCGLOWAT _IOR('s', 3, u_long) /* get low
watermark */
#define SIOCATMARK _IOR('s', 7, u_long) /* at oob mark?
*/
/*
* Structures returned by network data base library, taken
from the
* BSD file netdb.h. All addresses are supplied in host
order, and
* returned in network order (suitable for use in system
calls).
*/
struct hostent {
char FAR * h_name; /* official name of
host */
char FAR * FAR * h_aliases; /* alias list */
short h_addrtype; /* host address type
*/
short h_length; /* length of address
*/
char FAR * FAR * h_addr_list; /* list of
addresses */
#define h_addr h_addr_list[0] /* address, for
backward compat */
};
/*
* It is assumed here that a network number
* fits in 32 bits.
*/
struct netent {
char FAR * n_name; /* official name of
net */
char FAR * FAR * n_aliases; /* alias list */
short n_addrtype; /* net address type
*/
u_long n_net; /* network # */
};
struct servent {
char FAR * s_name; /* official service
name */
char FAR * FAR * s_aliases; /* alias list */
short s_port; /* port # */
char FAR * s_proto; /* protocol to use
*/
};
struct protoent {
char FAR * p_name; /* official protocol
name */
char FAR * FAR * p_aliases; /* alias list */
short p_proto; /* protocol # */
};
/*
* Constants and structures defined by the internet system,
* Per RFC 790, September 1981, taken from the BSD file
netinet/in.h.
*/
/*
* Protocols
*/
#define IPPROTO_IP 0 /* dummy for
IP */
#define IPPROTO_ICMP 1 /* control
message protocol */
#define IPPROTO_GGP 2 /* gateway^2
(deprecated) */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_PUP 12 /* pup */
#define IPPROTO_UDP 17 /* user
datagram protocol */
#define IPPROTO_IDP 22 /* xns idp
*/
#define IPPROTO_ND 77 /*
UNOFFICIAL net disk proto */
#define IPPROTO_RAW 255 /* raw IP
packet */
#define IPPROTO_MAX 256
/*
* Port/socket numbers: network standard functions
*/
#define IPPORT_ECHO 7
#define IPPORT_DISCARD 9
#define IPPORT_SYSTAT 11
#define IPPORT_DAYTIME 13
#define IPPORT_NETSTAT 15
#define IPPORT_FTP 21
#define IPPORT_TELNET 23
#define IPPORT_SMTP 25
#define IPPORT_TIMESERVER 37
#define IPPORT_NAMESERVER 42
#define IPPORT_WHOIS 43
#define IPPORT_MTP 57
/*
* Port/socket numbers: host specific functions
*/
#define IPPORT_TFTP 69
#define IPPORT_RJE 77
#define IPPORT_FINGER 79
#define IPPORT_TTYLINK 87
#define IPPORT_SUPDUP 95
/*
* UNIX TCP sockets
*/
#define IPPORT_EXECSERVER 512
#define IPPORT_LOGINSERVER 513
#define IPPORT_CMDSERVER 514
#define IPPORT_EFSSERVER 520
/*
* UNIX UDP sockets
*/
#define IPPORT_BIFFUDP 512
#define IPPORT_WHOSERVER 513
#define IPPORT_ROUTESERVER 520
/* 520+1 also used
*/
/*
* Ports < IPPORT_RESERVED are reserved for
* privileged processes (e.g. root).
*/
#define IPPORT_RESERVED 1024
/*
* Link numbers
*/
#define IMPLINK_IP 155
#define IMPLINK_LOWEXPER 156
#define IMPLINK_HIGHEXPER 158
/*
* Internet address (old style... should be updated)
*/
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; }
S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
#define s_addr S_un.S_addr
/* can be used for most tcp
& ip code */
#define s_host S_un.S_un_b.s_b2
/* host on imp */
#define s_net S_un.S_un_b.s_b1
/* network */
#define s_imp S_un.S_un_w.s_w2
/* imp */
#define s_impno S_un.S_un_b.s_b4
/* imp # */
#define s_lh S_un.S_un_b.s_b3
/* logical host */
};
/*
* Definitions of bits in internet address integers.
* On subnets, the decomposition of addresses to host and
net parts
* is done according to subnet mask, not the masks here.
*/
#define IN_CLASSA(i) (((long)(i) & 0x80000000) ==
0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST 0x00ffffff
#define IN_CLASSA_MAX 128
#define IN_CLASSB(i) (((long)(i) & 0xc0000000) ==
0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST 0x0000ffff
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(i) (((long)(i) & 0xc0000000) ==
0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST 0x000000ff
#define INADDR_ANY (u_long)0x00000000
#define INADDR_LOOPBACK 0x7f000001
#define INADDR_BROADCAST (u_long)0xffffffff
#define INADDR_NONE 0xffffffff
/* Winsock extension */
#define ADDR_ANY INADDR_ANY
/*
* Socket address, internet style.
*/
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
#define WSADESCRIPTION_LEN 256
#define WSASYS_STATUS_LEN 128
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char
szDescription[WSADESCRIPTION_LEN+1];
char
szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
} WSADATA;
typedef WSADATA FAR *LPWSADATA;
/*
* Options for use with [gs]etsockopt at the IP level.
*/
#define IP_OPTIONS 1 /* set/get IP per-
packet options */
/*
* Definitions related to sockets: types, address families,
options,
* taken from the BSD file sys/socket.h.
*/
/*
* This is used instead of -1, since the
* SOCKET type is unsigned.
*/
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
/*
* Types
*/
#define SOCK_STREAM 1 /* stream socket */
#define SOCK_DGRAM 2 /* datagram socket
*/
#define SOCK_RAW 3 /* raw-protocol
interface */
#define SOCK_RDM 4 /* reliably-
delivered message */
#define SOCK_SEQPACKET 5 /* sequenced packet
stream */
/*
* Types -- Winsock extensions for socket types with the
following convention
*
SOCK[_REL|_UNREL][_ISOCH][_UNISEND|_UNIRECV][_STREAM|_DGRAM|
_DSTREAM]
*/
#define SOCK_REL_STREAM SOCK_STREAM
#define SOCK_REL_DSTREAM SOCK_SEQPACKET
#define SOCK_UNREL_DSTREAM 101
#define SOCK_REL_UNISEND_DSTREAM 102
#define SOCK_REL_UNIRECV_DSTREAM 103
#define SOCK_UNREL_UNISEND_DSTREAM 104
#define SOCK_UNREL_UNIRECV_DSTREAM 105
#define SOCK_REL_DGRAM 106
#define SOCK_UNREL_DGRAM SOCK_DGRAM
#define SOCK_REL_ISOCH_DSTREAM 201
#define SOCK_UNREL_ISOCH_DSTREAM 202
#define SOCK_UNREL_ISOCH_STREAM 203
/*
* Option flags per-socket.
*/
#define SO_DEBUG 0x0001 /* turn on debugging
info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had
listen() */
#define SO_REUSEADDR 0x0004 /* allow local
address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections
alive */
#define SO_DONTROUTE 0x0010 /* just use
interface addresses */
#define SO_BROADCAST 0x0020 /* permit sending of
broadcast msgs */
#define SO_USELOOPBACK 0x0040 /* bypass hardware
when possible */
#define SO_LINGER 0x0080 /* linger on close
if data present */
#define SO_OOBINLINE 0x0100 /* leave received
OOB data in line */
#define SO_DONTLINGER (int)(~SO_LINGER)
/*
* Additional options.
*/
#define SO_SNDBUF 0x1001 /* send buffer size
*/
#define SO_RCVBUF 0x1002 /* receive buffer
size */
#define SO_SNDLOWAT 0x1003 /* send low-water
mark */
#define SO_RCVLOWAT 0x1004 /* receive low-water
mark */
#define SO_SNDTIMEO 0x1005 /* send timeout */
#define SO_RCVTIMEO 0x1006 /* receive timeout
*/
#define SO_ERROR 0x1007 /* get error status
and clear */
#define SO_TYPE 0x1008 /* get socket type
*/
/*
* Winsock extension -- options
*/
#define SO_FLOWSPEC 0x2001 /* flow spec for
sockets */
#define SO_GROUP_FLOWSPEC 0x2002 /* flow spec for
socket groups */
#define SO_GROUP_ID 0x2003 /* sharing the
same physical connection */
#define SO_GROUP_PRIORITY 0x2004 /* the relative
priority with a group */
#define SO_MAX_DG_SIZE 0x2005 /* maximum
datagram size */
#define PVD_CALL_ID 0x3001 /* an opaque
Winsock call ID */
#define PVD_CONFIG 0x3002 /* configuration
info for service provider */
#define TAPI_DEVICE_ID 0x3003 /* a TAPI line
device ID */
/*
* TCP options.
*/
#define TCP_NODELAY 0x0001
/*
* Address families.
*/
#define AF_UNSPEC 0 /* unspecified */
#define AF_UNIX 1 /* local to host
(pipes, portals) */
#define AF_INET 2 /* internetwork:
UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp
addresses */
#define AF_PUP 4 /* pup protocols:
e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS
protocols */
#define AF_NS 6 /* XEROX NS
protocols */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer
manufacturers */
#define AF_DATAKIT 9 /* datakit protocols
*/
#define AF_CCITT 10 /* CCITT protocols,
X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link
interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel
*/
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style
addresses */
/*
* Address families -- Winsock extensions.
*/
#define AF_IPX 18 /* IPX/SPX addresses
*/
#define AF_POTS_IT 19 /* POTS addresses
for Intel Transport */
#define AF_ISDNQMUX_IT 20 /* ISDN addresses
for Intel Transport */
#define AF_INET_SPE 21 /* Internet (SPE
version) */
#define AF_IPX_SPE 22 /* IPX/SPX (SPE
version) */
#define AF_NETBIOS_SPE 23 /* NetBios (SPE
version) */
#define AF_MAX 24
/*
* Structure used by kernel to store most
* addresses.
*/
struct sockaddr {
u_short sa_family; /* address family */
char sa_data[14]; /* up to 14 bytes of
direct address */
};
/*
* Structure used by kernel to pass protocol
* information in raw sockets.
*/
struct sockproto {
u_short sp_family; /* address family */
u_short sp_protocol; /* protocol */
};
/*
* Protocol families, same as address families for now.
*/
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_IMPLINK AF_IMPLINK
#define PF_PUP AF_PUP
#define PF_CHAOS AF_CHAOS
#define PF_NS AF_NS
#define PF_ISO AF_ISO
#define PF_OSI AF_OSI
#define PF_ECMA AF_ECMA
#define PF_DATAKIT AF_DATAKIT
#define PF_CCITT AF_CCITT
#define PF_SNA AF_SNA
#define PF_DECnet AF_DECnet
#define PF_DLI AF_DLI
#define PF_LAT AF_LAT
#define PF_HYLINK AF_HYLINK
#define PF_APPLETALK AF_APPLETALK
/*
* Protocol families -- Winsock extension
*/
#define PF_IPX AF_IPX
#define PF_POTS_IT AF_POTS_IT
#define PF_ISDNQMUX_IT AF_ISDNQMUX_IT
#define PF_INET_SPE AF_INET_SPE
#define PF_IPX_SPE AF_IPX_SPE
#define PF_NETBIOS_SPE AF_NETBIOS_SPE
#define PF_MAX AF_MAX
/*
* Structure used for manipulating linger option.
*/
struct linger {
u_short l_onoff; /* option on/off */
u_short l_linger; /* linger time */
};
/*
* Level number for (get/set)sockopt() to apply to socket
itself.
*/
#define SOL_SOCKET 0xffff /* options for
socket level */
/*
* Winsock extension -- level number for
(get/set)socketopt() to apply to service provider
* level.
*/
#define SOL_PROVIDER IPPROTO_TCP /* options for
service provider level */
/*
* Maximum queue length specifiable by listen.
*/
#define SOMAXCONN 5
#define MSG_OOB 0x1 /* process out-of-
band data */
#define MSG_PEEK 0x2 /* peek at incoming
message */
#define MSG_DONTROUTE 0x4 /* send without
using routing tables */
#define MSG_INTERRUPT 0x8 /* interrupt-time
send or recv */
#define MSG_MAXIOVLEN 0x10
/*
* Define constant based on rfc883, used by gethostbyxxxx()
calls.
*/
#define MAXGETHOSTSTRUCT 1024
/*
* Winsock extension -- WSABUF and QOS struct
*/
typedef struct _WSABUF {
int len; /* the length of the buffer */
char FAR * buf; /* the pointer to the buffer */
} WSABUF, FAR * LPWSABUF;
typedef enum _GUARANTEE {
GuaranteedService,
BestEffortService
} GUARANTEE;
typedef struct _flowparams {
int64 AverageBandwidth; /* in bytes/sec */
int64 PeakBandwidth; /* in bytes/sec */
int64 BurstLength; /* in microseconds
*/
int64 Latency; /* in microseconds */
int64 DelayVariation; /* in microseconds
*/
GUARANTEE LevelOfGuarantee; /* guaranteed or best
effort */
int32 CostOfCall /* reserved for
future; must be zero */
int32 ProviderId; /* provider
identifier */
int32 SizePSP; /* length of provider
specific parameters */
UCHAR ProviderSpecificParams[1]; /* provider
specific parameters */
} FLOWPARAMS;
typedef struct _QOS {
FLOWPARAMS ForwardFP; /* caller
(initiator) to callee */
FLOWPARAMS BackwardFP; /* callee to caller
*/
} QOS, FAR * LPQOS;
/*
* Winsock extension -- WSANETWORKEVENT
*/
typedef struct _WSANETWORKEVENT {
BOOL Fired;
int ErrorCode;
} WSANETWORKEVENT, FAR * LPWSANETWORKEVENT;
/*
* Winsock extension -- manifest constants for the return
value of the condition function
*/
#define CF_ACCEPT 0x0000
#define CF_REJECT 0x0001
#define CF_DEFER 0x0002
/*
* Winsock extension -- manifest constants for shutdown()
*/
#define SD_RECEIVE 0x00
#define SD_SEND 0x01
#define SD_BOTH 0x02
/*
* Winsock extension -- data type and manifest constants for
socket groups
*/
typedef unsigned int GROUP;
#define SG_UNCONSTRAINED_GROUP 0x01
#define SG_CONSTRAINED_GROUP 0x02
/*
* Define flags to be used with the WSPSelect() call.
*/
#define FD_READ 0x01L
#define FD_WRITE 0x02L
#define FD_OOB 0x04L
#define FD_ACCEPT 0x08L
#define FD_CONNECT 0x10L
#define FD_CLOSE 0x20L
/*
* Winsock extension -- new flags for WSPSelect()
*/
#define FD_QOS 0x40L
#define FD_GROUP_QOS 0x80L
/*
* All Winsock error constants are biased by WSABASEERR from
* the "normal"
*/
#define WSABASEERR 10000
/*
* Winsock definitions of regular Microsoft C error
constants
*/
#define WSAEINTR (WSABASEERR+4)
#define WSAEBADF (WSABASEERR+9)
#define WSAEACCES (WSABASEERR+13)
#define WSAEFAULT (WSABASEERR+14)
#define WSAEINVAL (WSABASEERR+22)
#define WSAEMFILE (WSABASEERR+24)
/*
* Winsock definitions of regular Berkeley error constants
*/
#define WSAEWOULDBLOCK (WSABASEERR+35)
#define WSAEINPROGRESS (WSABASEERR+36)
#define WSAEALREADY (WSABASEERR+37)
#define WSAENOTSOCK (WSABASEERR+38)
#define WSAEDESTADDRREQ (WSABASEERR+39)
#define WSAEMSGSIZE (WSABASEERR+40)
#define WSAEPROTOTYPE (WSABASEERR+41)
#define WSAENOPROTOOPT (WSABASEERR+42)
#define WSAEPROTONOSUPPORT (WSABASEERR+43)
#define WSAESOCKTNOSUPPORT (WSABASEERR+44)
#define WSAEOPNOTSUPP (WSABASEERR+45)
#define WSAEPFNOSUPPORT (WSABASEERR+46)
#define WSAEAFNOSUPPORT (WSABASEERR+47)
#define WSAEADDRINUSE (WSABASEERR+48)
#define WSAEADDRNOTAVAIL (WSABASEERR+49)
#define WSAENETDOWN (WSABASEERR+50)
#define WSAENETUNREACH (WSABASEERR+51)
#define WSAENETRESET (WSABASEERR+52)
#define WSAECONNABORTED (WSABASEERR+53)
#define WSAECONNRESET (WSABASEERR+54)
#define WSAENOBUFS (WSABASEERR+55)
#define WSAEISCONN (WSABASEERR+56)
#define WSAENOTCONN (WSABASEERR+57)
#define WSAESHUTDOWN (WSABASEERR+58)
#define WSAETOOMANYREFS (WSABASEERR+59)
#define WSAETIMEDOUT (WSABASEERR+60)
#define WSAECONNREFUSED (WSABASEERR+61)
#define WSAELOOP (WSABASEERR+62)
#define WSAENAMETOOLONG (WSABASEERR+63)
#define WSAEHOSTDOWN (WSABASEERR+64)
#define WSAEHOSTUNREACH (WSABASEERR+65)
#define WSAENOTEMPTY (WSABASEERR+66)
#define WSAEPROCLIM (WSABASEERR+67)
#define WSAEUSERS (WSABASEERR+68)
#define WSAEDQUOT (WSABASEERR+69)
#define WSAESTALE (WSABASEERR+70)
#define WSAEREMOTE (WSABASEERR+71)
/*
* Extended Winsock error constant definitions
*/
#define WSASYSNOTREADY (WSABASEERR+91)
#define WSAVERNOTSUPPORTED (WSABASEERR+92)
#define WSANOTINITIALISED (WSABASEERR+93)
/*
* Error return codes from gethostbyname() and
gethostbyaddr()
* (when using the resolver). Note that these errors are
* retrieved via WSAGetLastError() and must therefore follow
* the rules for avoiding clashes with error numbers from
* specific implementations or language run-time systems.
* For this reason the codes are based at WSABASEERR+1001.
* Note also that [WSA]NO_ADDRESS is defined only for
* compatibility purposes.
*/
#define h_errno WSAGetLastError()
/* Authoritative Answer: Host not found */
#define WSAHOST_NOT_FOUND (WSABASEERR+1001)
#define HOST_NOT_FOUND WSAHOST_NOT_FOUND
/* Non-Authoritative: Host not found, or SERVERFAIL */
#define WSATRY_AGAIN (WSABASEERR+1002)
#define TRY_AGAIN WSATRY_AGAIN
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
#define WSANO_RECOVERY (WSABASEERR+1003)
#define NO_RECOVERY WSANO_RECOVERY
/* Valid name, no data record of requested type */
#define WSANO_DATA (WSABASEERR+1004)
#define NO_DATA WSANO_DATA
/* no address, look for MX record */
#define WSANO_ADDRESS WSANO_DATA
#define NO_ADDRESS WSANO_ADDRESS
/*
* Winsock errors redefined as regular Berkeley error
constants
*/
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EALREADY WSAEALREADY
#define ENOTSOCK WSAENOTSOCK
#define EDESTADDRREQ WSAEDESTADDRREQ
#define EMSGSIZE WSAEMSGSIZE
#define EPROTOTYPE WSAEPROTOTYPE
#define ENOPROTOOPT WSAENOPROTOOPT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define EADDRINUSE WSAEADDRINUSE
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define ENETDOWN WSAENETDOWN
#define ENETUNREACH WSAENETUNREACH
#define ENETRESET WSAENETRESET
#define ECONNABORTED WSAECONNABORTED
#define ECONNRESET WSAECONNRESET
#define ENOBUFS WSAENOBUFS
#define EISCONN WSAEISCONN
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#define ELOOP WSAELOOP
#define ENAMETOOLONG WSAENAMETOOLONG
#define EHOSTDOWN WSAEHOSTDOWN
#define EHOSTUNREACH WSAEHOSTUNREACH
#define ENOTEMPTY WSAENOTEMPTY
#define EPROCLIM WSAEPROCLIM
#define EUSERS WSAEUSERS
#define EDQUOT WSAEDQUOT
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
#endif /* _WS2API_ */
/*
* Winsock SPI socket function prototypes
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef BOOL ( WSACALLBACK * LPBLOCKINGPROC )( VOID );
typedef VOID ( WSACALLBACK * LPCLEANUPPROC )( int ErrorCode,
DWORD
dwCallbackData );
typedef int ( WSACALLBACK * LPCONDITIONPROC )( LPWSABUF
lpCallerId,
LPWSABUF
lpCallerData,
LPWSABUF
lpCalleeId,
LPWSABUF
lpCalleeData,
GROUP FAR *
g,
DWORD
dwCallbackData );
typedef VOID ( WSACALLBACK LPSELECTPROC )( SOCKET s,
long lEvent,
int ErrorCode,
DWORD
dwCallbackData );
typedef VOID ( FAR * LPWSAUSERAPC )( DWORD dwContext );
SOCKET PASCAL FAR PSaccept (SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen,
int FAR * lpErrno);
int WSPAPI WSPBindWSPbind( SOCKET s,
const struct sockaddr FAR *name,
int namelen,
int FAR * lpErrno );
int WSPAPI WSPCloseSocketWSPclosesocket( SOCKET s,
int FAR * lpErrno );
int PASCAL FAR PSconnect (SOCKET s,
const struct sockaddr FAR *name,
int namelen,
int FAR * lpErrno);
int WSPAPI WSPGetPeerNameWSPgetpeername( SOCKET s,
struct sockaddr FAR *name,
int FAR * namelen,
int FAR * lpErrno );
int WSPAPI WSPGetSockNameWSPgetsockname( SOCKET s,
struct sockaddr FAR *name,
int FAR * namelen,
int FAR * lpErrno );
int WSPAPI WSPGetSockOptWSPgetsockopt( SOCKET s,
int level,
int optname,
char FAR * optval,
int FAR *optlen,
int FAR * lpErrno );
int WSPAPI WSPIoctlSocketWSPioctlsocket( SOCKET s,
long cmd,
u_long FAR *argp,
int FAR * lpErrno );
int WSPAPI WSPListenWSPlisten( SOCKET s,
int backlog,
int FAR * lpErrno );
int WSPAPI WSPSelectWSPselect( int nfds,
fd_set FAR *readfds,
fd_set FAR *writefds,
fd_set FAR *exceptfds,
const struct timeval FAR *timeout,
int FAR * lpErrno );
int WSPAPI WSPSetSockOptWSPsetsockopt( SOCKET s,
int level,
int optname,
const char FAR * optval,
int optlen,
int FAR * lpErrno );
int WSPAPI WSPShutdownWSPshutdown( SOCKET s,
int how,
int FAR * lpErrno );
/* Microsoft Windows Extension function prototypes */
SOCKET WSPAPI WSPAccept( SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen,
LPCONDITIONPROC lpfnCondition,
DWORD dwCallbackData,
int FAR * lpErrno );
int WSPAPI WSPAsyncSelect32( SOCKET s,
HWND hWnd,
unsigned int wMsg,
long lEvnet,
int FAR * lpErrno );
int WSPAPI WSPCallbackSelect16( SOCKET s,
LPSELECTPROC lpfnCallback,
DWORD dwCallbackData,
long lEvent,
int FAR * lpErrno );
int WSPAPI WSPCancelBlockingCall32( int FAR * lpErrno );
int WSPAPI WSPCleanup( LPCLEANUPPROC lpfnCallback,
DWORD dwCallbackData,
int FAR * lpErrno );
int WSPAPI WSPConnect( SOCKET s,
const struct sockaddr FAR *name,
int namelen,
LPWSABUF lpCallerData,
LPWSABUF lpCalleeData,
GROUP g,
LPQOS lpSFlowspec,
LPQOS lpGFlowspec,
int FAR * lpErrno );
int WSPAPI WSPEnumNetworkEvents( SOCKET s,
WSAEVNET hEventObject,
LPWSANETWORKEVENT
lpNetworkEvents,
LPINT lpiCount,
int FAR * lpErrno );
int WSPAPI WSPEventSelect( SOCKET s,
WSAEVENT hEventObject,
long lNetworkEvents,
int FAR * lpErrno );
BOOL WSPAPI WSPIsBlocking32( VOID );
int WSPAPI WSPRecvWSPrecv( SOCKET s,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRecv,
LPDWORD lpNumberOfBytesRecvd,
LPINT lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,
int FAR * lpErrno );
int WSPAPI WSPRecvFromWSPrecvfrom( SOCKET s,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRecv,
LPDWORD lpNumberOfBytesRecvd,
LPINT lpFlags,
LPVOID lpFrom,
LPINT lpFromlen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,
int FAR * lpErrno );
int WSPAPI WSPSendWSPsend( SOCKET s,
LPVOID lpBuffer,
DWORD nNumberOfBytesToSend,
LPDWORD lpNumberOfBytesSent,
int nFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,
int FAR * lpErrno );
int WSPAPI WSPSendToWSPsendto( SOCKET s,
LPVOID lpBuffer,
DWORD nNumberOfBytesToSend,
LPDWORD lpNumberOfBytesSent,
int nFlags,
LPVOID lpTo,
int nTolen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,
int FAR * lpErrno );
LPBLOCKINGPROC WSPAPI WSPSetBlockingHook32( LPBLOCKINGPROC
lpBlockFunc,
int FAR *
lpErrno );
SOCKET WSPAPI WSPSocket( int af,
int type,
int protocol,
DWORD dwProviderId,
int nFlags,
int FAR * lpErrno );
int WSPAPI WSPStartup( WORD wVersionRequired,
LPWSADATA lpWSAData );
int WSPAPI WSPUnhookBlockingHook32( int FAR * lpErrno );
/* Upcalls from service providers to the Winsock DLL */
SOCKETWSPAPI WPUXxxCreateSocketHandle( DWORD dwProviderId,
LPVOID lpContext,
int FAR * lpErrno );
int WSPAPI WPUXxxCloseSocketHandle( SOCKET s,
int FAR * lpErrno );
int WSPAPI WPUXxxQuerySocketHandleContext( SOCKET s,
LPVOID FAR *
lpContext,
int FAR * lpErrno );
int WSPAPI WPUXxxSetSocketHandleContext( SOCKET s,
LPVOID lpContext,
int FAR * lpErrno );
int WSPAPI WPUXxxQueueUserAPC32UserAPC( DWORD dwThreadId,
LPWSAUSERAPC lpfnUserApc,
DWORD dwContext,
int FAR * lpErrno );
DWORD WSPAPI WPUXxxGetCurrentThreadId32( VOID );
#ifdef __cplusplus
}
#endif
#ifndef _WS2API_
/* Microsoft Windows Extended data types */
typedef struct sockaddr SOCKADDR;
typedef struct sockaddr *PSOCKADDR;
typedef struct sockaddr FAR *LPSOCKADDR;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr_in *PSOCKADDR_IN;
typedef struct sockaddr_in FAR *LPSOCKADDR_IN;
typedef struct linger LINGER;
typedef struct linger *PLINGER;
typedef struct linger FAR *LPLINGER;
typedef struct in_addr IN_ADDR;
typedef struct in_addr *PIN_ADDR;
typedef struct in_addr FAR *LPIN_ADDR;
typedef struct fd_set FD_SET;
typedef struct fd_set *PFD_SET;
typedef struct fd_set FAR *LPFD_SET;
typedef struct hostent HOSTENT;
typedef struct hostent *PHOSTENT;
typedef struct hostent FAR *LPHOSTENT;
typedef struct servent SERVENT;
typedef struct servent *PSERVENT;
typedef struct servent FAR *LPSERVENT;
typedef struct protoent PROTOENT;
typedef struct protoent *PPROTOENT;
typedef struct protoent FAR *LPPROTOENT;
typedef struct timeval TIMEVAL;
typedef struct timeval *PTIMEVAL;
typedef struct timeval FAR *LPTIMEVAL;
/*
* Windows message parameter composition and decomposition
* macros.
*
* WSAMAKEASYNCREPLY is intended for use by Winsock
* when constructing the response to a WSAAsyncGetXByY()
routine.
*/
#define WSAMAKEASYNCREPLY(buflen,error)
MAKELONG(buflen,error)
/*
* WSAMAKESELECTREPLY is intended for use by Winsock
* when constructing the response to WSAAsyncSelect().
*/
#define WSAMAKESELECTREPLY(event,error)
MAKELONG(event,error)
/*
* WSAGETASYNCBUFLEN is intended for use by the Winsock
application
* to extract the buffer length from the lParam in the
response
* to a WSAGetXByY().
*/
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)
/*
* WSAGETASYNCERROR is intended for use by the Winsock
application
* to extract the error code from the lParam in the response
* to a WSAGetXByY().
*/
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
/*
* WSAGETSELECTEVENT is intended for use by the Winsock
application
* to extract the event code from the lParam in the response
* to a WSAAsyncSelect().
*/
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
/*
* WSAGETSELECTERROR is intended for use by the Winsock
application
* to extract the error code from the lParam in the response
* to a WSAAsyncSelect().
*/
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
#endif /* _WS2API_ */
#endif /* _WS2SPI_ */
Appendix B. Notes for Winsock Service Providers
B.1 Introduction
A Winsock service provider must implement ALL of the
applicable functionality described in the Winsock SPI
documentation. Validation of compliance is discussed in
section Error! Reference source not found.Error! Reference
source not found.Error! Reference source not found..
PII Version 1.1 implementations must support both TCP and
UDP type sockets. An implementation may support raw sockets
(of type SOCK_RAW), but their use is deprecated.
Certain Winsock SPIs documented above have special notes for
Winsock service provider implementors. A Winsock service
provider should pay special attention to conforming to the
Winsock SPI as documented. The Special Notes are provided
for assistance and clarification.
B.2 Winsock SPI Run Time Components
The run time component provided by each Winsock supplier is:
Component Description
Installation Program The Winsock service provider
installation program
Service Provider DLL The Winsock service provider
implementation DLL
B.3 Error Codes
In order to avoid conflict between various compiler
environments Winsock service providers MUST return the error
codes listed in the SPI specification, using the manifest
constants beginning with "WSA". The Berkeley-compatible
error code definitions are provided solely for compatibility
purposes for applications which are being ported from other
platforms.
Appendix C. Outstanding Issues
1. Does the 32-bit Windows Sockets 2 implementation live
in WSOCK32.DLL or WSOCK232.DLL?
What is the exact mechanism used for routing socket
handle-based requests to the proper provider? This
mechanism needs to be cognizant of TDI providers that
use "real" file system handles. {Is this an
architectural issue or an implementation issue. I would
suggest we avoid raising implimentation issues in our
public forum at this point in time.}
Does Windows 95 support 16- and 32-bit providers? If so,
the registry layout may need to be changed slighly to
specify both 16- and 32-bit provider DLLs. The registry
could be split into 16- and 32-bit subtrees, or
separate registry values could be used for the 16- and
32-bit DLLs. {I thought we had decided that there would
only be 32 bit providers in Windows 95}
The (16- and 32-bit) Windows Sockets DLLs could provide
"up call" entrypoints for use by the provider DLLs to
simplify configuration management. The Windows Sockets
DLLs could also provide entrypoints to simplify
provider installation. {Are these different upcalls
than are already included in this document? If so, I'm
not sure what you mean by "simplify configuration
mgmt". I believe we made a decision that the Winsock
DLLs would in fact provide entry points to simplify
installation. Even if we don't have these ready at this
time, we should put a place holder for them in the main
body of the document and not show them as an open
issue. }
2. Do the 16- and 32-bit providers use the same header
file (ws2spi.h)?
Need proper prefix for upcalls ("Xxx" is obviously just a
place-holder). {How about WSU for Winsock upcall ? It
would be nice not to have a relatively minor point like
this left in the Opens section.}
3. Should SPI functions that take socket descriptors also
take a context value? For providers that use "real" system
handles, this could always be NULL.
Should we support the SPI version as a separate concept
from the API version? {I think we are already set up to
be able to do this since we have separate version
negotiations between App and DLL and between DLL and
SP.}
Does the 32-bit WSPCleanup() really use the callback
function? {Again, is this architecture or
implementation? If implementation, lets move this to a
private list of implementation issues.}
4. How does a DLL-based protocol support graceful socket
close if an app immediately exits after calling
closesocket()? The provider & protocol DLLs will be detached
from the process (whose address space will go away
entirely), yet socket state needs to "linger" for the
graceful close.
5. Does the Winsock DLL close all sockets before calling
WSPCleanup(), or is WSPCleanup() responsible for closing all
open sockets?
_______________________________
1Note that there is a timing window between the accept()
call and the call to WSAAsyncSelect() to change the events
or wMsg. An application which desires a different wMsg for
the listening and accept()'ed sockets should ask for only
FD_ACCEPT events on the listening socket, then set
appropriate events after the accept(). Since FD_ACCEPT is
never sent for a connected socket and FD_READ, FD_WRITE,
FD_OOB, and FD_CLOSE are never sent for listening sockets,
this will not impose difficulties.
2 Because the callback is accessed at interrupt time, it
must reside in a DLL, and its code segment must be specified
as FIXED in the module-definition file for the DLL. Any data
that the callback accesses must be in a FIXED data segment
as well. The callback may not make any system calls except
for PostMessage, timeGetSystemTime, timeGetTime,
timeSetEvent, timeKillEvent, midiOutShortMsg,
midiOutLongMsg, and OutputDebugStr.
3 Note that there is a potential race condition here:
WINSOCK 2..DLL may get FD_READ, FD_WRITE or FD_ACCEPT
callback in interrupt time before it returns from
WSPAcceptEx(). Similar situations may happen to
PSConnectEx(), andany of the reenabling functions if they
are not invoked from within callback context.
4 However, due to the independence feature of sockets,
WINSOCK2.DLL may get a callback for one socket before the
callback for another socket has returned. WINSOCK2.DLL may
need to coordinate access to any common memory area shared
amongst these callback driven sockets.
5 Note that there is a potential race condition here:
WINSOCK2.DLL may get a callback in interrupt time even
before returning from WSPCallbackSelect(), in which case
WINSOCK2.DLL should proceed with the callback and assume
that WSPCallbackSelect() will return 0.
6Note that there is a timing window between the accept()
call and the call to WSAEventSelect() to change the network
events or hEventObject. An application which desires a
different hEventObject for the listening and accept()'ed
sockets should ask for only FD_ACCEPT network event on the
listening socket, then set appropriate network events after
the accept(). Since FD_ACCEPT never happens to a connected
socket and FD_READ, FD_WRITE, FD_OOB, and FD_CLOSE never
happen to listening sockets, this will not impose
difficulties.